XML Deep Dive

To any XML guru out there, I’m looking to dig beyond the simple example provided in the Xojo docs (book 3, Framework).

I have a set of fields that start with a root level I’ll call “project”. Within the project, I has a number of user selections and manually entered values. The issue that I’m having trouble with is how XMLItem, AppendChild and CreateElement tie into one another beyond the simple example provided for the teams and players.

Does anyone have a more detailed example that would demo a deeper nesting of nodes?

Thanks,
Tim

As a follow-up, I’ve added the following simple code to a method:

[code]
Dim theXML As New XmlDocument

// First Page
Dim root As XmlNode
root = theXML.CreateElement(“Production”)
Dim production As XmlNode
production = root.AppendChild(theXML.CreateElement(tfStudioInfo(0).Text))
production.SetAttribute(“ID”, tfStudioInfo(1).Text)
production.SetAttribute(“Name”, tfStudioInfo(0).Text)
production.SetAttribute(“Code Name”, tfStudioInfo(2).Text)
production.SetAttribute(“Studio”, tfStudioInfo(3).Text)
production.SetAttribute(“Vendors”, tfStudioInfo(4).Text)

Dim f As FolderItem
f = GetSaveFolderItem("", “TestXML.xml”)
If f <> Nil Then
theXML.SaveXml(f)
End If[/code]
However, the resulting .xml file does not have anything in it except the XML header:

<?xml version="1.0" encoding="UTF-8"?>

None of the nodes or attributes is added to the saved XML. Same thing happens in 13r4.1 and 12r2.1

Thoughts?

You have a problem where you define root. Try this:

Dim root As XmlNode = thexml.AppendChild(theXML.CreateElement("Production"))

(note the “theXML.CreateElement” inside the AppendChild, not just the string “Production”)’

Edit: a little more explanation, you need to create a new element in theXML, then append it to theXML. I just did it in one step there. You created the element but never added it. You could also add the line “theXML.appendChild root” after you set root=…

D’oh! Thanks @Bill Gookin! One more small step in the right direction. However, I can’t mark this as solved yet since I’m still unsure as to the more complex subsections.

Ah. Maybe Bill could have a look at the other XML post?

Everything pretty much gets added the same way - you create the element and append it, just like you did for the tfStudioInfo(0).Text child. Do you have an example of what you’re having troubles adding?

I have a bunch of extends that I use. They aren’t necessarily the best way to do things because I wrote them when I first started with RB (sigh) to help keep things similar to my old VB6 code, but you’re welcome to look at them.
XMLExtends.rbbas

Hopefully it’s fairly easy to figure out how to use it because I didn’t comment it. LOL But to add a child node to the “Production” node in your case with a text node inside it that looks like:

<person>Bill</person>

…you would do this:

retVal = root.AddChildNode("person", "Bill")

To get an attribute value you would do:

MsgBox production.GetAttrValue("ID")

There are a bunch of routines in there, please let me know if you need any help with them. I’ll try and document them a little better if anyone is interested.

Alexander - I’ll take a look at the other post…

Oh boy, I just looked through my code and realize that it’s been a looong time since I’ve looked at that code (it just works for me, so why look at it again, right?). There’s some stuff that’s not so wonderful in there, so don’t judge me! LOL

That gets me heading in the right direction, but the code posted now produces this:

<?xml version="1.0" encoding="UTF-8"?> <Production> <A DJ's Life ID="092-1433212" Name="A DJ's Life" Code Name="The Road to Ibiza" Studio="TOLIS Group Studios" Vendors="TOLIS Group, Inc."/> </Production>
Instead of the format I was expecting with each attribute being it’s own element.

For what I’m seeing, it would actually be easier for me to simply hand craft the XML that I’m looking for rather than using this lightly documented yet complex mechanism.

I got your post as I was typing and what you describe is exactly what I’m trying to achieve. I’ll have a look and see about updating and commenting as I go. Don’t worry about judgement - Im the spaghetti-code kid and I still believe in the usefulness of App.DoEvents() in a desktop app :S

How well versed are you in XML? That’s kind of a prerequisite, I think. I don’t want to presume, but it sounds like some of what you’re hitting has more to do with XML knowledge than Xojo. But I could be way off base.

Attributes are not elements. Your code generated the exact XML I would expect. If you want elements, you need to create elements and then add the text nodes to them:

[code] Dim theXML As New XmlDocument

// First Page
Dim root As XmlNode
root = theXML.AppendChild(theXML.CreateElement(“Production”))
Dim production As XmlNode

Dim value As XmlNode

Dim id As XmlNode
id = root.AppendChild(theXML.CreateElement(“ID”))
value = id.AppendChild(theXML.CreateTextNode(“092-1433212”))

Dim name As XmlNode
name = root.AppendChild(theXML.CreateElement(“Name”))
value = name.AppendChild(theXML.CreateTextNode(“A DJ’s Life”))

Dim codename As XmlNode
codename = root.AppendChild(theXML.CreateElement(“Code Name”))
value = codename.AppendChild(theXML.CreateTextNode(“The Road to Ibiza”))

Dim studio As XmlNode
studio = root.AppendChild(theXML.CreateElement(“Studio”))
value = studio.AppendChild(theXML.CreateTextNode(“TOLIS Group Studios”))

Dim vendor As XmlNode
vendor = root.AppendChild(theXML.CreateElement(“Vendors”))
value = vendor.AppendChild(theXML.CreateTextNode(“TOLIS Group, Inc.”))

Dim f As FolderItem
f = GetSaveFolderItem(“”, “TestXML.xml”)
If f <> Nil Then
theXML.SaveXml(f)
End If[/code]

Did you want this?

<?xml version="1.0" encoding="UTF-8"?>
<Production xmlns:xml="http://www.w3.org/XML/1998/namespace">
  <FirstRecord><ID>ID value</ID>
    <Name>Name value</Name>
    <Code Name>Code name value</Code Name>
    <Studio>Studio value</Studio>
    <Vendors>Vendors value</Vendors>
  </FirstRecord>
</Production>

If so, you can do this (requires my extends to get the AddChildNode method):

[code]
Dim theXML As New XmlDocument

// First Page
Dim root As XmlNode
root = theXML.CreateElement(“Production”)
theXML.AppendChild root

Dim production As XmlNode = root.AddChildNode(“FirstRecord”, “”)
call production.AddChildNode(“ID”, “ID value”)
call production.AddChildNode(“Name”, “Name value”)
call production.AddChildNode(“Code Name”, “Code name value”)
call production.AddChildNode(“Studio”, “Studio value”)
call production.AddChildNode(“Vendors”, “Vendors value”)

dim c as new Clipboard
c.SetText theXML.FormatXML[/code]

Right. What Paul said. :slight_smile:

Exactly what I’m trying to achieve.

Okay, then the code I put will work (that’s how I got the XML, formatted with the FormatXML routine). If you wanted to add more to one of the nodes, say the ID node, you’d need to actually keep the return value (which is an XMLNode) like:

Dim idNode as XMLNode = production.AddChildNode(“ID”, “ID value”)

Then you could work with idNode and add other stuff to it if you needed to. But if you’re just doing a quick add to it, you can use “call” instead. Of course, you might want to add some error checking and other nonsense like that. :wink:

This information is exactly what’s missing from the Framework guide. Now, it’s all clear and I can put the rat poison back in the garage… :slight_smile:

One last question - is there any way to control the EOL used by the XML export? Linux isn’t liking the result exported by OS X… When I manually edit the file and reset the EOL to Unix EOL, it’s happy.

I’ll see what I can do there. I can certainly add a version of the XML and sample code that uses elements and text nodes for the player names rather than elements and attributes. I like attributes. :slight_smile:

Doesn’t like it how?

I don’t see a way to change the EOL character when saving using SaveXML.

Of course, you could instead save the XML yourself using ToString with a TextOutputStream and format it using a Transform.

And that’s what the FormatXML routine in my extends routines file does. :slight_smile:

Since the nodes are being added as elements of “root”, is it safe to reuse the node variable as your code reuses the value node?

i.e.:

[code] Dim root As XmlNode
root = theXML.AppendChild(theXML.CreateElement(“Production”))

Dim theNode As XmlNode
Dim value As XmlNode

theNode = root.AppendChild(theXML.CreateElement(“ID”))
value = theNode.AppendChild(theXML.CreateTextNode(“092-1433212”))

theNode = root.AppendChild(theXML.CreateElement(“Name”))
value = theNode.AppendChild(theXML.CreateTextNode(“A DJ’s Life”))
[/code]