VB中SelectSingleNode查询多命名空间XML节点返回Nothing问题
问题根源
查询返回Nothing的核心原因是XML根节点<Invoice>绑定了无前缀的默认命名空间urn:oasis:names:specification:ubl:schema:xsd:Invoice-2,但代码中未对该默认命名空间做前缀映射。MSXML的XPath 1.0实现规则中,无前缀的节点名只会匹配无命名空间的节点,不会自动匹配文档中声明的默认命名空间下的节点,因此路径查询无法命中目标。
修复方法
- 在命名空间配置中,给根节点的默认命名空间分配一个自定义前缀(比如
inv) - 调整XPath查询路径,属于默认命名空间的根节点
Invoice必须带上自定义的前缀,优先使用从根节点出发的绝对路径,不要滥用//做全局匹配(全局匹配性能差,还可能误命中文档中其他位置的同名节点)
修正后的代码
Dim dom As New MSXML2.DOMDocument60 Dim nod As IXMLDOMNode Dim branch As String Dim Ns As String ' 补充根节点默认命名空间的前缀映射 Ns = "xmlns:inv='urn:oasis:names:specification:ubl:schema:xsd:Invoice-2' " & _ "xmlns:cbc='urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2' " & _ "xmlns:cac='urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2'" With dom .SetProperty "SelectionNamespaces", Ns .async = False .Load xFile End With ' 从根节点写绝对查询路径,根节点必须带默认命名空间对应的前缀 branch = "/inv:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PostalAddress/cac:Country/cbc:IdentificationCode" Set nod = dom.selectSingleNode(branch) If Not nod Is Nothing Then ' 读取节点值,此处将返回"RO" Debug.Print nod.Text End If Set dom = Nothing
注意事项
- 所有在XML中通过
xmlns="xxx"声明的默认命名空间,在MSXML中做XPath查询时都必须手动注册前缀,没有例外 - DOMDocument60默认开启命名空间校验,不要为了省事关闭命名空间支持,会导致XML结构解析异常
- 固定结构的XML查询优先使用绝对路径,比
//开头的相对全局查询性能更高,也能避免同名节点匹配错误
内容的提问来源于stack exchange,提问作者Adelina Andreea trandafir
相关产品推荐
相关产品推荐

