XML Parsing Woes

I’m trying to parse some XML, and having a few challenges. I was hoping somebody could help advise what I’m doing wrong.

The following XML is stored in a document

<?xml version='1.0' encoding='UTF-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Body> <ns:getCCMVersionResponse xmlns:ns="http://www.cisco.com/AXL/API/11.5"><return> <componentVersion> <version>11.5.1.10000(6)</version> </componentVersion> </return> </ns:getCCMVersionResponse> </soapenv:Body> </soapenv:Envelope>

I created a method to load the XML from a string into a document, which seems to work fine. I then try and parse the contents of the “version” element, but i’m getting an empty set back.

[code]
Dim root As XmlNode
root = xmlResult.DocumentElement

//Dim nsgetCCMVersionResponseNode as XmlNode
//Dim componentVersionNode as XmlNode
Dim versionNode As XmlNode

For version As Integer = 0 To root.ChildCount - 1

// Add Version

versionNode = root.Child(version)
msgbox(versionNode.toString)
msgbox(versionNode.GetAttribute(“version”))

Next[/code]

My first messagebox gives me the entire (unparsed) XML as follows

<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><ns:getCCMVersionResponse xmlns:ns="http://www.cisco.com/AXL/API/11.5"><return><componentVersion><version>11.5.1.10000(6)</version></componentVersion></return></ns:getCCMVersionResponse></soapenv:Body>

My second message box is coming back empty, but I would expect to get the following

11.5.1.10000(6)

Any thoughts on what I’m doing wrong here? I have virtually no experience parsing XML, so assume I’m a complete noob :slight_smile:

XML is a tree structure. You need to traverse the tree.

DocumentElement is the Envelope node. It has a single child, Body.
In this case, Body has a single child, getCCMVersionResponse.
getCCMVersionResponse has a single child, componentVersion.
componentVersion has a single child, Version.
Version has a single child, an unnamed Text Node.
That Text Node has the value, “11.5.1.10000(6)”.

I went that direction earlier without success (you can see where I defined a few other levels) but I think i may have missed a level. Let me re-attack it from that direction and give it a shot. Thanks!

One thing that’s hard to wrap your head around at first is that last node, Version. You would expect it to have the Value directly, but it does not. It holds yet another node that has the Value.

You can also look at XQL … something like this:

Dim nodes As XmlNodeList nodes = xml.XQL("//version") // Find all version nodes .. in your sample, there is only one // Loop through results Dim node As XmlNode For i As Integer = 0 To nodes.Length - 1 //this assumes there is at least one returned node node = nodes.Item(i) msgbox(node.toString) Next

Ok Tim, I’ve added the additional levels, but as you describe, I think I’m falling short on that last node.

Dim root As XmlNode
root = xmlResult.DocumentElement

Window1.XMLList.DeleteAllRows

Dim getCCMVersionResponseNode as XmlNode
Dim componentVersionNode as XmlNode
Dim versionNode As XmlNode

For getCCMVersionResponse As Integer = 0 To root.ChildCount - 1
  For componentVersion As Integer = 0 To root.ChildCount - 1
    For version As Integer = 0 To root.ChildCount - 1
      
      // Add Version
      
      versionNode = root.Child(version)
      msgbox(versionNode.toString)
      msgbox(versionNode.GetAttribute("version"))
      
    Next
  Next
Next

You’re still not traversing the tree.

Dim root As XmlNode
root = xmlResult.DocumentElement

Window1.XMLList.DeleteAllRows

Dim body as XmlNode
Dim getCCMVersionResponseNode as XmlNode
Dim componentVersionNode as XmlNode
Dim versionNode As XmlNode
dim version as String

body = root.FirstChild
getCCMVersionResponseNode = body.FirstChild
componentVersionNode  = getCCMVersionResponseNode.FirstChild
versionNode = componentVersionNode.FirstChild
version = versionNode.FirstChild.Value

Note that I am making assumptions about the structure of the XML document. That’s fine for many applications, such as this one. For more flexibility, use XQL as Jeff suggests.

So is it unnecessary to nest the for loops like I was doing? I thought that was how I traversed the tree.

I’m still getting a blank result on that final ‘version’ msgbox. Current code as follows

Dim root As XmlNode
root = xmlResult.DocumentElement

Dim body as XmlNode
Dim getCCMVersionResponseNode as XmlNode
Dim componentVersionNode as XmlNode
Dim versionNode As XmlNode
dim version as String

body = root.FirstChild
getCCMVersionResponseNode = body.FirstChild
componentVersionNode  = getCCMVersionResponseNode.FirstChild
versionNode = componentVersionNode.FirstChild
version = versionNode.FirstChild.Value
msgbox(versionNode.toString)
msgbox(version)

if it’s only for a small text search, you can use Instr to search for “”, then search for “”
and then use the Mid function to get the string between them.

Long term its going to be for detailed results retrieval for some pretty involved data sets, so I’m trying to learn an approach that will give me the best support for that.

I just noticed there is a node in between getCCMVersionResponseNode and componentVersionNode.

I recommend you get this simple case working and maybe sketch the tree out on paper. Every is a separate node. Everything directly below it is a child node. The stuff inside them you have to traverse the child to get to.

<level1>
     <level2>
           <level3>stuff</level3>
     </level2>
     <level2>
          <level3>other stuff</level3>
     </level2>
</level1>

Here is one level1 node that has 2 children, level2. Each of those nodes has a level3 child. You might traverse this tree with

dim level1, level2, level3 as XmlNode

level1 = xmldoc.DocumentElement
for i as integer = 0 to level1.ChildCount -1
    level2 = level1.Child(i)    // <---- this is the part you were missing
    for j as integer = 0 to level2.ChildCount - 1
        level3 = level2.Child(j)
        msgbox level3.FirstChild.Value
    next j
next i

Once you get comfortable manually traversing a known structure, look at XQL. It allows you to search the XML document for tags. But it can be more complicated, especially with namespaces.