使用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转换,它将生成一个带有文档命名空间的节点集。
答案 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
。