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 "<P><B>Bold</B></P>"
- trace(my_textnode.nodeValue);
// traces "<P><B>Bold</B></P>"
-
- my_xml.firstChild.appendChild(my_textnode);
- trace(my_xml);
// traces "<text><P><B>
Bold</B></P></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.
|