使用OPENXML解析IIS MetaBase.xml

时间:2011-04-19 10:03:55

标签: sql-server xml iis

我正在尝试将IIS 6服务器上的网站列表添加到SQL-Server表中。我知道我可以使用WMI等获得它但是这需要在盒子上运行额外的服务,而我应该能够通过使用OPENXML获取proc来解析MetaBase.xml文件来找到信息。

对于那些不熟悉MetaBase.xml的人,相关部分看起来有点像:

<configuration xmlns="urn:microsoft-catalog:XML_Metabase_V64_0">
  <MBProperty>
    <IIsWebDirectory Location="/LM/W3SVC/1/ROOT/MySite1" AppFriendlyName="MySite1" AppIsolated="2" AppPoolId="MySite1" AppRoot="/LM/W3SVC/1/ROOT/MySite1" DontLog="TRUE">     
    </IIsWebDirectory>
    <IIsWebDirectory Location="/LM/W3SVC/1/ROOT/MySite2" AppFriendlyName="MySite2" AppIsolated="2" AppPoolId="MySite2" AppRoot="/LM/W3SVC/1/ROOT/MySite2" DontLog="TRUE">     
    </IIsWebDirectory>
  </MBProperty>
</configuration>

我正在使用以下SQL来尝试解析它:

DECLARE @XMLPath VARCHAR(MAX)
SELECT @XMLPath = 'C:\Temp\MetaBase.xml'

DECLARE @RawXML XML, @sql NVARCHAR(4000), @params NVARCHAR(4000), @handle INT
SELECT @sql = N'SELECT @res = (SELECT * FROM OPENROWSET (BULK '''+ @XMLPath +''', SINGLE_BLOB)x)'
SELECT @params = N'@res XML OUTPUT'
EXEC sp_executesql @sql, @params, @res = @RawXML OUTPUT

SELECT @RawXML

EXEC sp_xml_preparedocument @handle OUTPUT, @RawXML
SELECT * 
FROM OPENXML(@handle, 'MBProperty/IISWebDirectory', 3) WITH (AppFriendlyName VARCHAR(800), Location VARCHAR(800), AppRoot VARCHAR(800), AppPoolId VARCHAR(800), DefaultDoc VARCHAR(800))
EXEC sp_xml_removedocument @handle

我看到XML已正确加载到@RawXML中,但从OPENXML查询中得不到任何内容。我猜它可能与路径有关,但尝试过多种组合(例如'configuration / MBProperty / IISWebDirectory')无济于事。

2 个答案:

答案 0 :(得分:3)

您需要在路径中添加configuration并将IISWebDirectory更改为IIsWebDirectory,因为XML区分大小写,您需要添加xpath_namespaces参数。

EXEC sp_xml_preparedocument @handle OUTPUT, @RawXML, '<root xmlns:ns="urn:microsoft-catalog:XML_Metabase_V64_0" />'

SELECT * 
FROM OPENXML(@handle, 'ns:configuration/ns:MBProperty/ns:IIsWebDirectory', 3) WITH
  (AppFriendlyName VARCHAR(800),
   Location VARCHAR(800),
   AppRoot VARCHAR(800),
   AppPoolId VARCHAR(800),
   DefaultDoc VARCHAR(800))
EXEC sp_xml_removedocument @handle

或者您可以直接查询XML变量。

;with xmlnamespaces ('urn:microsoft-catalog:XML_Metabase_V64_0' as ns)
select
  n.i.value('@AppFriendlyName', 'varchar(800)') as AppFriendlyName,
  n.i.value('@Location', 'varchar(800)') as Location,
  n.i.value('@AppRoot', 'varchar(800)') as AppRoot,
  n.i.value('@AppPoolId', 'varchar(800)') as AppPoolId,
  n.i.value('@DefaultDoc', 'varchar(800)') as DefaultDoc
from @RawXML.nodes('ns:configuration/ns:MBProperty/ns:IIsWebDirectory') as n(i)

答案 1 :(得分:3)

我将在这里扮演恶魔倡导者,并建议这是错误的做法。

元数据库文件并不总是最新的。 IIS缓存配置数据库更新并定期将其刷新到磁盘。我在使用ADSI或WMI更改属性与在服务器负载下刷新到磁盘之间经历了长达5分钟的延迟。

您说您需要额外的服务才能在计算机上运行以收集此数据。当然,您还需要某种过程来从元数据库文件中收集这些数据吗?

另一个非常重要的原因是,当您解析此文件时,您需要自己解析继承的属性。 IIS6配置数据库的主要技术设计方面之一是属性继承。

例如,如果您正在收集脚本地图,那么这是一个继承的属性。除非您在站点,虚拟目录或应用程序上显式设置ScriptMapDefaultDoc(或其他一些继承的属性),否则您需要向后移动元数据库树以查找此内容值。

那是为你自己制作一根杆子。您应该使用API​​(ADSI,System.DirectoryServices [最差阻力路径的API]或WMI)来查询元数据库,而不是直接读取此文件。相信我,我以前来过这里。