When working with XML using MSXML2, it's pretty well documented that for any XPath queries to work, you need to define the selectionNamespaces property. However, this is only a straightforward fix if you always know what the namespaces are. I'm writing a module in VBA that I hope to be able to use to parse all the Office XML formats, and I'd like a function that can arbitrarily define the namespaces for documents as I load them.
At present, I've found the following isn't a bad first stab:
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
With a couple of subtle changes for dealing with the default namespace. However, this won't work very fell with XML like the following:
<?xml>
<root xmlns:t="MyFirstNS">
<t:object1>
<r:object2 xmlns:r="MySecondNS" />
</t:object1>
</root>
</xml>
Aside from traversing, is there an approach that might be better than mine for dealing with this kind issue = i.e. any namespace not defined in the root node? Ideal would be an XPATH 1.0 expression that will select all xmlns attribute nodes even when the namespace they exist in has yet to be added to SelectionNamespaces, or help building an XSLT transform that will produce a nodeset with the namespaces of a document.