如何使用MSXML2检测外部XML文档中的命名空间?

时间:2014-03-21 12:58:36

标签: xml vba xslt xpath namespaces

使用MSXML2处理XML时,很好地记录了要使任何XPath查询起作用,您需要定义selectionNamespaces属性。但是,如果您始终知道名称空间是什么,这只是一个简单的解决方案。我在VBA中编写了一个模块,我希望能够用它来解析所有的Office XML格式,我希望能够在加载文档时随意定义文档的命名空间。

目前,我发现以下不是第一次不好的事情:

Public DoDefineNamespaces(strRootNodeName As String, strFilePath As String, ByRef oMyDoc As MSXML2.DomDocument60)
    Dim oRootNode As MSXML2.IXMLDomNode
    Dim oMyDoc As MSXML2.DomDocument60
    Dim oAttribute As MSXML2.IXMLDomNode
    Sim strNamespaces As String

    Set oMyDoc = New MSXML2.DomDocument60
    oMyDoc.Load strFilePath
    Set oRootNode = oMyDoc.SelectNodes("./*[name()='" & strRootNodeName & "']")
    For Each oAttribute In oRootNode.Attributes
        If oAttribute.Namespace = "http://www.w3.org/2000/xmlns/" Then 
            strNamespaces = strNamespaces & oAttribute.Xml
        End If
    Next oAttribute
    oMyDoc.SetProperty("SelectionNamespaces", strNamespaces)
End Sub

通过一些微妙的更改来处理默认命名空间。但是,这项工作不会像以下那样在XML中失败:

<?xml>
<root xmlns:t="MyFirstNS">
   <t:object1>
       <r:object2 xmlns:r="MySecondNS" />
   </t:object1>
</root>
</xml>

除了遍历之外,是否有一种方法可能比我的方法更好地处理这种问题=即根节点中没有定义的任何命名空间?理想的是XPATH 1.0表达式,它将选择所有xmlns属性节点,即使它们存在的命名空间尚未添加到SelectionNamespaces,或者帮助构建一个XSLT转换,它将生成一个带有文档命名空间的节点集。

1 个答案:

答案 0 :(得分:1)

要确定文档中使用的所有名称空间,请使用此XPath 1.0查询:

/*/namespace::*

这将包括重复项。

对于XPath 2.0,您可以选择

distinct-values(//*/fn:namespace-uri())

而不推荐使用命名空间轴。两者都只返回实际使用中的命名空间(并省略了未使用的命名空间)。此查询已删除重复的命名空间。

无论如何:如果你不关心命名空间,那么忽略它们可能更合理。在XPath 1.0中,您必须使用通配符轴步骤并在谓词中执行名称测试。要将所有元素<foo/>与任意名称空间匹配,请在XPath 2.0中分别使用//*[local-name() = 'foo'] //*:foo