Introduction to XML in Flash
       by senocular

XML Methods
The following XML methods are used to create and edit XML.

new XML("xml text");
Number 1 is the XML object itself and the call to the constructor that lets you create XML instances. If you're working with XML in Flash, you'll simply need to have one of these.

There should be nothing new here. If you've been following along up to this point, you've noticed this used a few times. The optional parameter that lets you generate XML within the instance created right off the bat. Passing an XML string, written just as XML would be written in an external XML document, into the constructor call will let you define XML directly within the instance without needing to load in an external document. Example:

var my_xml = new XML("<letter><to>senocular</to><body>Get a life</body></letter>");
trace(my_xml.status); // traces "0" (No error)
trace(my_xml.firstChild.nodeName); // traces "letter"
trace(my_xml.firstChild.firstChild.nodeName); // traces "to"
trace(my_xml.firstChild.firstChild.firstChild.nodeValue); // traces "senocular"

Easy! ...next

XMLInstance.parseXML("xml text");
This method basically condenses the constructor's action into a method letting you create XML for your instance by passing in XML text. Any XML created this way will replace any current XML existing in the object. So, you may be thinking why not just redefine the variable with a new XML object via a constructor call? Well, using parseXML lets you retain any custom properties assigned to the XML object or settings such as ignoreWhite.

var my_xml = new XML();
my_xml.parseXML("<letter><to>senocular</to><body>send money</body></letter>");
trace(my_xml.firstChild.firstChild.firstChild.nodeValue); // traces "senocular"
trace(my_xml.firstChild.childNodes[1].firstChild.nodeValue); // traces "send money"

Again, easy. Notice, though, that parseXML is a method of an XML instance and not for use on an XMLNode. This means it can't be used selectively on parts of internal XML. Other methods, however, do allow for that.

XMLInstance.createElement("node name");
This one is kind of self explanatory. It creates an element. Now, the catch is that the createElement method does not create an element within the XML instance that it's used on. Instead, a homeless, "free floating" element node is returned from the createElement call. The instance calling it is just a host for spitting this guy out. This free floating element can then be inserted into whatever XML instance you want within any node using other XML methods like appendChild and insertBefore.

The text passed into createElement, "node name," is the desired name for the element created. This is not a tag (using < and >) like text used in parseXML, just a name. The tag aspect of the created node is automatic. So, if it is your intent to create the element <bob />, then you would pass "bob" not "<bob />" into createElement.

var my_xml = new XML();
trace(my_xml); // traces ""
var my_element = my_xml.createElement("bob");
trace(my_element); // traces "<bob />"
trace(my_xml); // still traces ""

 

XMLInstance.createTextNode("text value");
This is just like createElement but it creates a text node instead, using string passed in to represent its nodeValue (or its text). It too, like createElement, returns a "free floating" node which exists no where until you decide to put it somewhere.

var my_xml = new XML();
trace(my_xml); // traces ""
var my_textnode = my_xml.createTextNode("What about");
trace(my_textnode.nodeValue); // traces "What about"
trace(my_xml); // still traces ""

Note: there is no direct method to create CDATA sections using any particular current ActionScript method as Flash just treats them like text nodes anyway. The good news is that the createTextNode method will actually transform unacceptable characters (<, >, &, ', and ") passed to it into their respective character entity references if you're worried about having invalid characters going into your text nodes. This makes it acceptable for storing markup like HTML too so long as you don't mind the character entity references being used. Using nodeValue within Flash will give you the markup with without character entity references while the toString method (what you normally see with a trace) will show you the actual XML text as it really exists with character entity references.

var my_xml = new XML("<text/>");
var my_textnode = my_xml.createTextNode("<P><B>Bold</B></P>");
trace(my_textnode.toString()); // traces "&lt;P&gt;&lt;B&gt;Bold&lt;/B&gt;&lt;/P&gt;"
trace(my_textnode.nodeValue); // traces "<P><B>Bold</B></P>"
 
my_xml.firstChild.appendChild(my_textnode);
trace(my_xml); // traces "<text>&lt;P&gt;&lt;B&gt;
Bold&lt;/B&gt;&lt;/P&gt;</text>"

 

XMLNodeInstance.appendChild(childNode);
Pretty much everything called directly off of XML instances was facilitating creation. Now that we're in the XMLNode instance methods, we're dealing with manipulation. The appendChild method takes a node and throws it to the set of elements making that XML node's children putting it at the end of the list. Using this and insertNode (to be covered next) is where a good bulk of the action is when fiddling with the structure of your XML internally in Flash. Using one of these two methods lets you find a home for those free floaters created with createElement and createTextNode. When used on nodes already existing within an XML structure, it will move them to the specified XMLNode instance - this so long as the node is not moved into the same set of children in which it already exists. In other words, appendChild cannot reorder, just move nodes to other parents.

var my_xml = new XML();
var node = my_xml.createElement("pickup");
my_xml.appendChild(node);
node = my_xml.createElement("truck");
my_xml.firstChild.appendChild(node);
trace(my_xml); // traces "<pickup><truck /></pickup>"
 
node = my_xml.createTextNode("Drive Me!");
my_xml.firstChild.firstChild.appendChild( node);
trace(my_xml); // traces "<pickup><truck>Drive Me!</truck></pickup>"
 
node = my_xml.createElement("car")
my_xml.firstChild.appendChild(node);
trace(my_xml); // traces "<pickup><truck>Drive Me!</truck><car /></pickup>"
 
my_xml.firstChild.appendChild( my_xml.firstChild.firstChild.firstChild );
trace(my_xml); // traces
"<pickup><truck /><car />Drive Me!</pickup>"

Here createElement and createTextNode create nodes which are then added to the my_xml XML instance (or a node within) using appendChild. Each time the node is added as a child at the end of other children of the parent element. You can see this more specifically with the car element which, when added, was added after the previously appended truck element.

The last part shows how appendChild can be used to move nodes. This, however, would not have worked if you tried to append truck to pickup. Though common sense tells you it would move to the end, the appendChild method would actually fail since you're trying to append to the same parent in which the node passed already exists - and Flash just doesn't like the idea of that. Moving nodes within their parents will be addressed later in using custom functions.

XMLNodeInstance.insertBefore(childNode, beforeNode);
The insertBefore method is similar to that of appendChild. The main difference is that insertBefore lets you reach all the positions within an element's child set that appendChild can't reach. While appendChild throws nodes at the end of a collection of children, insertBefore puts them everywhere else, and actually, includes the end as well.

When using insertBefore, you use a reference to the node you wish to insert (childNode) and a reference to the node in which its supposed to be inserted before (beforeNode). Take note that this is not an index or position number, its the actual child node that exists within the XMLNode instance insertBefore is being used on. If you pass an illegal node reference, something that is a node but a node that is not a child of the node instance this insertBefore was used on, the method will fail. So really, the function looks more like this:

beforeNode.parentNode.insertBefore(childNode, beforeNode);

or

XMLNodeInstance.insertBefore(childNode, XMLNodeInstance.childNodes[n]);

If you pass a non-node value into the beforeNode parameter, the childNode will be, by default, inserted at the end of the child nodes list as if using appendChild. Note that not using any beforeNode parameter at all or passing null will cause the method to fail.

var my_xml = new XML("<baseballfield />");
var node = my_xml.createElement("firstbase");
my_xml.firstChild.appendChild(node);
node = my_xml.createElement("thirdbase");
my_xml.firstChild.appendChild(node);
node = my_xml.createElement("secondbase");
var thirdbase = my_xml.firstChild.childNodes[1];
my_xml.firstChild.insertBefore(node, thirdbase);
trace(my_xml); // traces "<baseballfield><firstbase />
<secondbase /><thirdbase /></baseballfield>"

The secondbase node was a little late in being created (either that or the thirdbase element cut in line!) so he needed to jump back in his rightful spot. The insertBefore method allowed this in passing thirdbase as the node in which it needed to be inserted in front of.

XMLNodeInstance.cloneNode(deep);
This method takes an existing node, copies it, and returns it as a new node. The deep parameter (why they chose "deep" to describe this parameter is beyond me) determines whether or not all of the child nodes of the cloned node are also copied and cloned along with it. If deep is true, child nodes are included in the copy. If false, the element is copied as an empty element with no children but retains any attributes it may have. It may be better to think of this as the "include children?" parameter.

var my_xml = new XML("<aliens><invader>SuperKiller</invader></aliens>");
var clone_with_children = my_xml.firstChild.firstChild.cloneNode(true);
var empty_clone = my_xml.firstChild.firstChild.cloneNode(false);
my_xml.firstChild.appendChild(clone_with_children);
my_xml.firstChild.appendChild(empty_clone);
trace(my_xml); // traces <aliens><invader>SuperKiller
</invader><invader>SuperKiller</invader><invader /></aliens>

Notice how the last invader, the second one appended, doesn't have a "SuperKiller" text node in it. This is because the deep (or "include children?") argument was false meaning no children were copied over into the returned clone node.

XMLNodeInstance.removeNode();
Last but not least, removeNode. It should be pretty apparent what this method does. Its the equivalent to MovieClip.removeMovieClip, only it removes nodes instead of movie clips. This is how you get rid of unwanted nodes in your XML object or other nodes within. Example:

var my_xml = new XML("<life><fun /><money /><friends /><taxes /></life>");
trace(my_xml); // traces "<life><fun /><money /><friends /><taxes /></life>"
my_xml.firstChild.childNodes[3].removeNode();
trace(my_xml); // traces "<life><fun /><money /><friends /></life>"

Understand that all attributes and child nodes of removed nodes are removed right along with them. If you want to retain child nodes but ditch the parent (how often have we wanted to ditch our parents as a kid?) then later we can discuss a way to do through a custom function.


 




SUPPORTERS:

kirupa.com's fast and reliable hosting provided by Media Temple.