How to query an XML file with namespaced attribute

2019-08-10 07:13发布

问题:

Thanks for an AWESOME forum it truly is a wealth of knowledge and hopefully in searching for a solution I can help someone else.

I wonder if some kind soul could help me by suggesting how to or possibly pointing me in the right direction with a code example to parse the xml code shown here. I have been searching all over the web for a vbscript example but am really battling to find one that solves the problem.

Most of the examples on the web show how to extract certain tags or text matches in nodes or child nodes and don't quite explain hot to reference the portions I am interested in in this code.

I already have python code which works fine but the vbscript has me stumped :-(

The xmlDOC defines a vAPP's environment settings, the parts I am interested in are: oe:key and oe:value for each of the node under <PropertySection>.

I need to have the key and the value stored in a text file with entries like

bootflag=a
clusetername=cluster test

etc. Here is the XML doc:

<Environment xmlns="http://schemas.dmtf.org/ovf/environment/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oe="http://schemas.dmtf.org/ovf/environment/1" xmlns:ve="http://www.vmware.com/schema/ovfenv" oe:id="" ve:vCenterId="vm-167">
 <PlatformSection>
  <Kind>VMware ESXi</Kind>
  <Version>5.5.0</Version>
  <Vendor>VMware, Inc.</Vendor>
  <Locale>en</Locale>
 </PlatformSection>
 <PropertySection>
  <Property oe:key="bootflag" oe:value="A"/>
  <Property oe:key="clustername" oe:value="custer test"/>
  <Property oe:key="datacenter_name" oe:value="datacenter test"/>
  <Property oe:key="dns1" oe:value="192.168.1.198"/>
  <Property oe:key="domain" oe:value="zen.com"/>
  <Property oe:key="gateway" oe:value="192.168.1.1"/>
  <Property oe:key="hostname" oe:value="rambo1"/>
  <Property oe:key="ip" oe:value="192.168.1.104"/>
  <Property oe:key="netmask" oe:value="255.255.255.0"/>
  <Property oe:key="vcenter_password" oe:value="vpass"/>
  <Property oe:key="vcenterip" oe:value="1.2.3.4"/>
  <Property oe:key="vcenteruser" oe:value="vcenteruser"/>
 </PropertySection>
 <ve:EthernetAdapterSection>
  <ve:Adapter ve:mac="00:50:56:88:62:8a" ve:network="VM Network" ve:unitNumber="7"/>
  <ve:Adapter ve:mac="00:50:56:88:46:25" ve:network="VM Network" ve:unitNumber="8"/>
  <ve:Adapter ve:mac="00:50:56:88:31:59" ve:network="VM Network" ve:unitNumber="9"/>
  <ve:Adapter ve:mac="00:50:56:88:5e:00" ve:network="VM Network" ve:unitNumber="10"/>
 </ve:EthernetAdapterSection>
</Environment>

I would really appreciate any help.


EDIT: Based on the reply below I tried this bit of code but I'm sure I'm going wrong with filling in the node info, specifically "oe:key" and "oe:value".

Please find the update code below:

Set objDoc = CreateObject("MSXML.DOMDocument")
objDoc.Load ("c:\Temp\ovfenv.xml")
' Iterate over all elements contained in the <root> element:
Set objRoot = objDoc.documentElement

s = ""
t = ""
For Each child in objRoot.childNodes
   s = s & child.getAttribute("oe:key") & " "
   t = t & child.getAttribute("oe:value") & " "
Next
MsgBox s    
MsgBox t    

' Find a particular element using XPath:
Set objNode = objDoc.selectSingleNode("/PropertySection/Property[@oe:key='bootflag']")
MsgBox objNode.getAttribute("oe:value")

回答1:

You almost had it.

You must - in MSXML just like in every other API implementation - declare any namespaces you intend to use in XPath.

Option Explicit  ' that's always a good idea, too!
Dim doc, ns, node

Set doc = CreateObject("MSXML.DOMDocument")
doc.Load "C:\Temp\ovfenv.xml"

ns = "xmlns:oe='http://schemas.dmtf.org/ovf/environment/1'"
doc.setProperty "SelectionNamespaces", ns

Set node = doc.selectSingleNode("//PropertySection/Property[@oe:key = 'bootflag']/@oe:value")

If Not node Is Nothing Then
  MsgBox node.nodeValue
Else
  MsgBox "Nothing found!"
End If


回答2:

Check out fmunkert's answer -> Here

More specifically, the code he documented here:

Set objDoc = CreateObject("MSXML.DOMDocument")
objDoc.Load "C:\Temp\Test.xml"

' Iterate over all elements contained in the <root> element:

Set objRoot = objDoc.documentElement
s = ""
t = ""
For Each child in objRoot.childNodes
   s = s & child.getAttribute("name") & " "
   t = t & child.getAttribute("value") & " "
Next
MsgBox s    ' Displays "alpha beta gamma "
MsgBox t    ' Displays "1 2 3 "

' Find a particular element using XPath:

Set objNode = objDoc.selectSingleNode("/root/property[@name='beta']")
MsgBox objNode.getAttribute("value")     ' Displays 2