XML DOM 带有命名空间的 SelectSingleNode() 不返回节点
XML DOM SelectSingleNode() with namespace not returning the node
我在 MSXML 中遇到了 selecting 带有命名空间的节点的问题。 XML 由 ADODB 记录集生成,如下所示:
<xml>
<s:Schema id="RowsetSchema" >
<s:ElementType name="row" content="eltOnly" rs:updatable="true" >
<s:AttributeType name="ID" rs:number="1" rs:basecatalog="SystemDB" rs:basetable="pagehits" rs:basecolumn="ID" rs:keycolumn="true" rs:autoincrement="true" >
<s:datatype dt:type="int" dt:maxLength="4" rs:precision="10" rs:fixedlength="true" rs:maybenull="false" />
</s:AttributeType>
<s:AttributeType name="SessionCode" rs:number="2" rs:writeunknown="true" rs:basecatalog="SystemDB" rs:basetable="pagehits" rs:basecolumn="SessionCode" >
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="36" rs:fixedlength="true" rs:maybenull="false" />
</s:AttributeType>
<s:AttributeType name="PagePath" rs:number="3" rs:writeunknown="true" rs:basecatalog="SystemDB" rs:basetable="pagehits" rs:basecolumn="PagePath" >
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="100" rs:maybenull="false" />
</s:AttributeType>
<s:AttributeType name="PersID" rs:number="4" rs:writeunknown="true" rs:basecatalog="SystemDB" rs:basetable="pagehits" rs:basecolumn="PersID" >
<s:datatype dt:type="int" dt:maxLength="4" rs:precision="10" rs:fixedlength="true" rs:maybenull="false" />
</s:AttributeType>
<s:AttributeType name="PersonInfo" rs:number="5" rs:writeunknown="true" rs:basecatalog="SystemDB" rs:basetable="pagehits" rs:basecolumn="PersonInfo" >
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="100" rs:maybenull="false" />
</s:AttributeType>
<s:AttributeType name="CRD" rs:number="6" rs:writeunknown="true" rs:basecatalog="SystemDB" rs:basetable="pagehits" rs:basecolumn="CRD" >
<s:datatype dt:type="dateTime" rs:dbtype="timestamp" dt:maxLength="16" rs:scale="3" rs:precision="23" rs:fixedlength="true" rs:maybenull="false" />
</s:AttributeType>
<s:extends type="rs:rowbase" />
</s:ElementType>
</s:Schema>
<rs:data>
<z:row ID="1" SessionCode="2CA43F6A-3951-42C5-8FF4-C6409026ED3A" PagePath="/pages/home/home.asp" PersID="2" PersonInfo="User395959" CRD="2014-04-07T23:30:38.090000000" />
<z:row ID="2" SessionCode="2CA43F6A-3951-42C5-8FF4-C6409026ED3A" PagePath="/pages/home/home.asp" PersID="2" PersonInfo="User395959" CRD="2014-04-07T23:30:51.180000000" />
<z:row ID="3" SessionCode="2CA43F6A-3951-42C5-8FF4-C6409026ED3A" PagePath="/pages/home/home_v02.asp" PersID="2" PersonInfo="User395959" CRD="2014-04-07T23:30:51.240000000" />
<z:row ID="4" SessionCode="2CA43F6A-3951-42C5-8FF4-C6409026ED3A" PagePath="/pages/home/home.asp" PersID="2" PersonInfo="User395959" CRD="2014-04-07T23:30:54.180000000" />
<z:row ID="5" SessionCode="2CA43F6A-3951-42C5-8FF4-C6409026ED3A" PagePath="/pages/home/home_v02.asp" PersID="2" PersonInfo="User395959" CRD="2014-04-07T23:30:54.213000000" />
</rs:data>
</xml>
我已将 XML 字符串加载到名为 oXMLDoc 的 XML 文档中。我现在想要 select s:Schema 节点,所以我使用此代码 select 节点并报告 selected 节点对象的类型:
oXMLDoc.setProperty "SelectionNamespaces", " xmlns:s='http://dev.kauupm.com/ns_s' "
dim oSchemaNode: set oSchemaNode = oXMLDoc.DocumentElement.SelectSingleNode("//s:Schema")
oTracer.Trace "", "Schema node is type: " & typeName(oSchemaNode)
tracer上报的结果是type为Nothing,所以没有找到节点。
我尝试了多种不同的 xpath 组合都无济于事。但是,如果我在将 XML 文本加载到 XML 对象之前从 XML 文本中删除所有名称空间,那么 select 没有名称空间的 Schema 节点就可以正常工作!所以,问题出在命名空间的某个地方,但我看不出我做错了什么,我很困惑。
我正在使用 Msxml2.FreeThreadedDOMDocument.6.0.
非常感谢任何帮助 - 约翰
出现这个问题的原因在于没有理解前缀表示的命名空间必须匹配。 ADODB 记录集生成的源 xml 有自己的命名空间,声明如下:
xmlns:rs='urn:schemas-microsoft-com:rowset'
xmlns:z='#RowsetSchema'
xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882'
xmlns:dt='uuid:C2F41010-65B3-11d1-A29F-00AA00C14882'
我在 setProperty 参数中使用了不同的命名空间。因此,尽管我在 selectSingleNode 调用的路径中使用了 s: 前缀,但相应的命名空间与 XML.
中 s: 前缀的命名空间不匹配
所以我把setProperty改成了
'// Set the namespaces used for selection - they must match the namespaces from Microsoft
oXMLDoc.setProperty "SelectionNamespaces", " xmlns:xsl='http://www.w3.org/1999/XSL/Transform' " _
& " xmlns:rs='urn:schemas-microsoft-com:rowset' " _
& " xmlns:z='#RowsetSchema' " _
& " xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882' " _
& " xmlns:dt='uuid:C2F41010-65B3-11d1-A29F-00AA00C14882' "
现在它完美运行了。
没想到前缀只是代表命名空间的符号,必须匹配的是命名空间,而不仅仅是前缀。
非常感谢@helderdarocha。
约翰
我在 MSXML 中遇到了 selecting 带有命名空间的节点的问题。 XML 由 ADODB 记录集生成,如下所示:
<xml>
<s:Schema id="RowsetSchema" >
<s:ElementType name="row" content="eltOnly" rs:updatable="true" >
<s:AttributeType name="ID" rs:number="1" rs:basecatalog="SystemDB" rs:basetable="pagehits" rs:basecolumn="ID" rs:keycolumn="true" rs:autoincrement="true" >
<s:datatype dt:type="int" dt:maxLength="4" rs:precision="10" rs:fixedlength="true" rs:maybenull="false" />
</s:AttributeType>
<s:AttributeType name="SessionCode" rs:number="2" rs:writeunknown="true" rs:basecatalog="SystemDB" rs:basetable="pagehits" rs:basecolumn="SessionCode" >
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="36" rs:fixedlength="true" rs:maybenull="false" />
</s:AttributeType>
<s:AttributeType name="PagePath" rs:number="3" rs:writeunknown="true" rs:basecatalog="SystemDB" rs:basetable="pagehits" rs:basecolumn="PagePath" >
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="100" rs:maybenull="false" />
</s:AttributeType>
<s:AttributeType name="PersID" rs:number="4" rs:writeunknown="true" rs:basecatalog="SystemDB" rs:basetable="pagehits" rs:basecolumn="PersID" >
<s:datatype dt:type="int" dt:maxLength="4" rs:precision="10" rs:fixedlength="true" rs:maybenull="false" />
</s:AttributeType>
<s:AttributeType name="PersonInfo" rs:number="5" rs:writeunknown="true" rs:basecatalog="SystemDB" rs:basetable="pagehits" rs:basecolumn="PersonInfo" >
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="100" rs:maybenull="false" />
</s:AttributeType>
<s:AttributeType name="CRD" rs:number="6" rs:writeunknown="true" rs:basecatalog="SystemDB" rs:basetable="pagehits" rs:basecolumn="CRD" >
<s:datatype dt:type="dateTime" rs:dbtype="timestamp" dt:maxLength="16" rs:scale="3" rs:precision="23" rs:fixedlength="true" rs:maybenull="false" />
</s:AttributeType>
<s:extends type="rs:rowbase" />
</s:ElementType>
</s:Schema>
<rs:data>
<z:row ID="1" SessionCode="2CA43F6A-3951-42C5-8FF4-C6409026ED3A" PagePath="/pages/home/home.asp" PersID="2" PersonInfo="User395959" CRD="2014-04-07T23:30:38.090000000" />
<z:row ID="2" SessionCode="2CA43F6A-3951-42C5-8FF4-C6409026ED3A" PagePath="/pages/home/home.asp" PersID="2" PersonInfo="User395959" CRD="2014-04-07T23:30:51.180000000" />
<z:row ID="3" SessionCode="2CA43F6A-3951-42C5-8FF4-C6409026ED3A" PagePath="/pages/home/home_v02.asp" PersID="2" PersonInfo="User395959" CRD="2014-04-07T23:30:51.240000000" />
<z:row ID="4" SessionCode="2CA43F6A-3951-42C5-8FF4-C6409026ED3A" PagePath="/pages/home/home.asp" PersID="2" PersonInfo="User395959" CRD="2014-04-07T23:30:54.180000000" />
<z:row ID="5" SessionCode="2CA43F6A-3951-42C5-8FF4-C6409026ED3A" PagePath="/pages/home/home_v02.asp" PersID="2" PersonInfo="User395959" CRD="2014-04-07T23:30:54.213000000" />
</rs:data>
</xml>
我已将 XML 字符串加载到名为 oXMLDoc 的 XML 文档中。我现在想要 select s:Schema 节点,所以我使用此代码 select 节点并报告 selected 节点对象的类型:
oXMLDoc.setProperty "SelectionNamespaces", " xmlns:s='http://dev.kauupm.com/ns_s' "
dim oSchemaNode: set oSchemaNode = oXMLDoc.DocumentElement.SelectSingleNode("//s:Schema")
oTracer.Trace "", "Schema node is type: " & typeName(oSchemaNode)
tracer上报的结果是type为Nothing,所以没有找到节点。
我尝试了多种不同的 xpath 组合都无济于事。但是,如果我在将 XML 文本加载到 XML 对象之前从 XML 文本中删除所有名称空间,那么 select 没有名称空间的 Schema 节点就可以正常工作!所以,问题出在命名空间的某个地方,但我看不出我做错了什么,我很困惑。
我正在使用 Msxml2.FreeThreadedDOMDocument.6.0.
非常感谢任何帮助 - 约翰
出现这个问题的原因在于没有理解前缀表示的命名空间必须匹配。 ADODB 记录集生成的源 xml 有自己的命名空间,声明如下:
xmlns:rs='urn:schemas-microsoft-com:rowset'
xmlns:z='#RowsetSchema'
xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882'
xmlns:dt='uuid:C2F41010-65B3-11d1-A29F-00AA00C14882'
我在 setProperty 参数中使用了不同的命名空间。因此,尽管我在 selectSingleNode 调用的路径中使用了 s: 前缀,但相应的命名空间与 XML.
中 s: 前缀的命名空间不匹配所以我把setProperty改成了
'// Set the namespaces used for selection - they must match the namespaces from Microsoft
oXMLDoc.setProperty "SelectionNamespaces", " xmlns:xsl='http://www.w3.org/1999/XSL/Transform' " _
& " xmlns:rs='urn:schemas-microsoft-com:rowset' " _
& " xmlns:z='#RowsetSchema' " _
& " xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882' " _
& " xmlns:dt='uuid:C2F41010-65B3-11d1-A29F-00AA00C14882' "
现在它完美运行了。
没想到前缀只是代表命名空间的符号,必须匹配的是命名空间,而不仅仅是前缀。
非常感谢@helderdarocha。
约翰