Using XML

XML is a standard protocol for transferring, storing, and reading data for several purposes, including application initialization parameters, data sets, and remote procedure calls. Flex applications work with XML by using Flash Player’s native support.

Flash Player 9 supports two mechanisms for working with XML: a legacy XMLDocument class and the new XML class that implements the ECMAScript for XML (E4X) standard. All XML examples in this book use E4X unless otherwise noted.

Creating XML Objects

There are two ways to create XML objects in ActionScript: using XML literals or with the XML constructor. XML literals are useful when you want to define the XML data directly in the code and you know the exact XML data you want to use. The following example defines an XML literal and assigns it to a variable:

var xml:XML = <books>
              <book>
                <title>Programming Flex 3</title>
                <authors>
                  <author first="Chafic" last="Kazoun" />
                  <author first="Joey" last="Lott" />
                </authors>
              </book>
              <book>
                <title>ActionScript 3.0 Cookbook</title>
                <authors>
                  <author first="Joey" last="Lott" />
                  <author first="Keith" last="Peters" />
                  <author first="Darron" last="Schall" />
                </authors>
              </book>
            </books>;

Note

We’ll assume that this is the XML object referenced by the remainder of the XML examples in this chapter.

If you aren’t able to define the XML data directly in ActionScript, you can load the data as a string and pass it to the XML constructor. In the following example, loadedXMLData is a variable containing XML data loaded from an external source at runtime:

var xml:XML = new XML(loadedXMLData);

When you use the XML constructor, any string data you pass to the constructor is parsed into the XML object as XML nodes. By default, Flash Player attempts to interpret all string data as XML. That means it interprets whitespace (carriage returns, tabs, etc.) as XML nodes. That can cause unexpected results. Therefore, if the XML string data you pass to an XML constructor contains extra whitespace (for formatting purposes) that you don’t want interpreted as XML nodes, you should first set the static ignoreWhitespace property to true for the XML class, as shown here:

XML.ignoreWhitespace = true;
var xml:XML = new XML(loadedXMLData);

Reading XML Data

Once you have an XML object, you can read from the object. There are two basic ways in which you can read the data: by traversing the Document Object Model (DOM) or by accessing the data using E4X syntax. The two techniques are not exclusive of one another: you can use them in conjunction with one another.

Note

In each case that outputs an XML node, the following examples use the toXMLString() method to format the XML node as a string.

When viewing the XML data in light of the DOM, treat it simply as a hierarchical structure of data consisting of parent and child nodes. When looking at the DOM, focus primarily on the structure rather than the content. You can retrieve all the content from an XML object by treating it in this manner, but you access the data by structure by stepping into the XML one node at a time. The XML class defines a host of methods for retrieving DOM structure information, including the following:

children()

The children() method returns an XMLList object with all the child nodes of an XML object. The XMLList class implements a very similar interface to that of XML, and all of the methods discussed in this section apply to both XML and XMLList. An XMLList object is essentially an array of XML or XMLList objects. You can even retrieve elements from an XMLList object using array access notation. For example, the following code retrieves the book nodes as an XMLList. It then displays the first element from that list.

var bookNodes:XMLList = xml.children();
trace(bookNodes[0].toXMLString());
length()

The length() method returns the number of elements. For XML objects, this always returns 1. For XMLList objects, it may return more than 1. The following example illustrates the children() and length() methods used in conjunction. This example displays the titles of each of the books:

var bookNodes:XMLList = xml.children();
for(var i:uint = 0; i < bookNodes.length(); i++) {
  trace(bookNodes[i].children()[0].toXMLString());
}
parent()

You can retrieve the parent of an XML or XMLList object using the parent() method. For example, the following displays the first book node by accessing the title node first, and then it retrieves the parent of that node:

trace(xml.children()[0].children()[0].parent().toXMLString());
attributes()

The attributes() method returns an XMLList object with all the data from the attributes contained within an XML object. You can call the name() method for each attribute in the XMLList to retrieve the name of the attribute as a string. You can then use that value as a parameter, which you can pass to the attribute() method of the XML object to retrieve the value of the attribute. The following example illustrates how this works:

var author0:XML = xml.children()[0].children()[1].children()[0];
var attributes:XMLList = author0.attributes();
var attributeName:String;
for(var i:uint = 0; i < attributes.length(); i++) {
  attributeName = attributes[i].name();
  trace(attributeName + " " + author0.attribute(attributeName));
}

As you can see, traversing the XML DOM is effective but laborious. Often, it’s far more effective to use E4X syntax, particularly when you already know the structure. E4X syntax allows you to access child nodes by name as properties of parent nodes. For example, the following accesses the first book node:

trace(xml.book[0]);

You can chain together this simple E4X syntax as in the following example, which retrieves the first author node of the first book node:

trace(xml.book[0].authors.author[0].toXMLString());

E4X also allows you to easily access attributes using the @ symbol. The following uses this syntax to retrieve the value of the first attribute of the author node:

trace(xml.book[0].authors.author[0].@first);

You can also use E4X filters. Filters are enclosed in parentheses within which you specify conditions. The following example retrieves all the author nodes in which the last attribute is Kazoun:

var authors:XMLList = xml.book.authors.author.(@last == "Kazoun");
for(var i:uint = 0; i < authors.length(); i++) {
  trace(authors[i].parent().parent().toXMLString());
}

Writing to and Editing XML Objects

You can also write to and edit XML objects using ActionScript. There are three things you can do in this category:

  • Modify existing data.

  • Add new data.

  • Remove existing data.

You can modify existing data using the same E4X syntax you use to read the data on the left side of an assignment statement. For example, the following changes the title of the first book:

xml.book[0].title = "Programming Flex 3: Edition 1";

The following example changes the name of the second author of the first book:

xml.book[0].authors.author[1].@first = "Joseph";

If you want to add new data, you can use the appendChild(), prependChild(), insertChildBefore(), and insertChildAfter() methods. Each method inserts a new XML node into an XML or XMLList structure. The appendChild() and prependChild() methods each accept one parameter and insert the node at the end and at the beginning of the structure, respectively. The following adds a new publisher node to each book:

xml.book[0].appendChild(<publisher>O'Reilly</publisher>);
xml.book[1].appendChild(<publisher>O'Reilly</publisher>);

You can use the insertChildBefore() and insertChildAfter() methods to add a new node before or after an existing node. The methods each require two parameters: the new node to add, and a reference to the existing node. The following adds a new publication date node (publicationDate) between the authors and publisher nodes:

xml.book[0].insertChildAfter(xml.book[0].authors, <publicationDate>2006</
publicationDate>);
xml.book[1].insertChildAfter(xml.book[1].authors, <publicationDate>2006</
publicationDate>);

You can remove elements using the delete operator. The following example first adds a new middle attribute to an author node and then removes it:

xml.book[0].authors.author[1] = <author first="Joey" middle="Persnippity" last="Lott"
/>;
trace(xml.book[0].authors);
delete xml.book[0].authors.author[1].@middle;
trace(xml.book[0].authors);

Get Programming Flex 3 now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.