XML Parsing

I have a simple XML file like this:

<?xml version="1.0"?> <DOCUMENT> <apple>pie</apple> <banana>split</banana> <cherry>tart</cherry> <grape>bubblegum</grape> </DOCUMENT>

I am using code like this…

[code]Dim x As FolderItem = GetFolderItem(MyPath)
Dim xml as New XmlDocument
xml.LoadXml(x)

Dim root as XmlNode
root = xml.DocumentElement
j = root.ChildCount

Dim docnode as XmlNode
Dim docname as String
docnode = root.Child(0)[/code]

This seems to retrieve the 0th (First) child of the document.
However; I want to be able to retrieve the element by NAME, not by index, and
ultimately I want the VALUE associated with that specific NAME.

something like this:

docnode = root.GetAttributeNode("apple") docname = docnode.value
or

docname = root.GetAttribute("apple") 

I’ve tried about every combination of XmlElement and XmlNode I can think of in conjunction with GetAttribute, and GetAttributeNode to try and find the magic combination that lets me grab specific element values by their name. Alas the solution eludes me. I’ll keep futzing with it, but I figure the community is chock full of people who have been down this road. Most of the combinations I’ve tried will compile and execute but they produce nil for docnode (unless I use an index) and I never get docname to receive a value no matter what I’ve tried.

Edit (Paul): Added code formatting tags.

You need to loop through the nodes and look at the names. You also don’t have to try every combination you can think of… things like this are covered in the documentation.

Also try looking at XMLNode.XQL in Xojo’s Language Reference. There’s an example that shows how to iterate through nodes and get their data.

As Tim and John have said, your options are to loop through the nodes to find the one(s) you want or to use XQL to search for what you want.

To start with looping, first this code loads up your XML (saved in a constant called kXML):

[code]Dim xml As New XmlDocument
xml.LoadXml(kXML)

Dim root As XmlNode = xml.DocumentElement

Dim node As XmlNode = FindByNodeName(root, “cherry”)
MsgBox(node.FirstChild.Value)[/code]

it calls the FindByNodeName method which loops through the nodes looking for the one with the name that was passed in. It’s code:

[code]Public Function FindByNodeName(root As XmlNode, name As String) as XmlNode
// Loop through children and return the node that
// matches the supplied name

Dim nodeCount As Integer = root.ChildCount

For i As Integer = 0 To nodeCount - 1
If root.Child(i).Name = name Then
Return root.Child(i)
End If
Next
End Function[/code]

Using XQL you would provide the XQL search criteria and then loop through the results:

[code]Dim xml As New XmlDocument
xml.LoadXml(kXML)

Dim root As XmlNode = xml.DocumentElement
Dim nodes As XmlNodeList
nodes = root.XQL("//cherry") // Find all cherry nodes in XML

// Loop through results and display each name attribute
Dim node As XmlNode
For i As Integer = 0 To nodes.Length - 1
node = nodes.Item(i)
MsgBox("Value: " + node.FirstChild.Value)
Next[/code]

FWIW not sure about the performance hit, but nowadays with all the json out there, I just started converting xml to json via xslt

Only did one simple stream for now and it seems fine so far.

Ok, I hadn’t tried to iterate through all the nodes, and inspect them. I was kinda hoping the parser would lend a little more help. I’m used to working with XML in PHP. Of course I looked at the online documentation, and it seemed to imply that I could request attributes and or nodes by name.

XMLNode.GetAttribute returns a String and not an XMLAttribute.
XMLNode.GetAttributeNode returns an XMLAttribute and not an XMLNode
XMLAttribute says it represents an attribute node.
XMLElement - I’m not sure how this fits together with Nodes and Attributes.

My point being: These Xojo classes can be a bit confusing if you haven’t worked with them.
Doesn’t seem like I should have to iterate over each child and ask “are you the one with the name I’m looking for?”

I’ve got dozens of attributes by name I want to extract from tens of thousands of xml files.
So as Iterate over each child… I need to check if its ANY of the elements I’m looking for, which I suppose is better than making multiple passes seeking out each child. The JSON parser is more helpful. I suppose XML has too many variants to create a more in depth parser.

No disrespect to any of the responders here, Special shout out to Tim and John. I marked Pauls response as the answer because I thought it would be the most helpful to people who might stumble upon this in the future.

If you don’t want to do lots of looping, then you’ll want to look more into XQL (aka XPath) which offers lots of ways for you to query the XML to get what you’re looking for.