Chapter 16. How Do I Work with XML?

16.0 Introduction

XML (Extensible Markup Language) is a flexible way to structure data for storage, transmission, and parsing. Traditional name-value pairs, used by standard GET and POST form actions, are fine for transferring small amounts of simple data. However, this technique isn’t well suited for large amounts of data or when you have to carefully organize the data.

For example, name-value pairs are limited to associations that link a single value with a single variable. Complex associations where variables must be grouped in some manner are arguably impossible, or would require multiple variables with similar names.. You could get a basic database-like structure this way with name-value pairs:

?user1namefirst=John&user1namelast=Public&
user1joined=2007&user1reg=yes&

Using XML, however, you can easily associate related variables. The preceding name-value pair submission could be represented this way in XML:

<user>
    <first>John</first>
    <last>Public</last>
    <joined reg="yes">2007</joined>
</user>

You can imagine, when this data enlarges to many users, how much more easily you can work with a single variable that contains data that’s organized consistently.

Although this book discusses ActionScript 3.0’s ability to manipulate XML, it can’t delve into the basics of XML. However, you’ll find a bountiful supply of information online. One such resource is the World Wide Web Consortium home for XML coverage, http://www.w3c.org/XML/.

For the purposes of this chapter, you must know only a few basic things, to understand any errors you may see when experimenting.

All but a few administrative tags are self-defined. You need only decide how to structure your content in a consistent manner so that both the server (if present) and client can understand it.

  • Tags and attributes must be of a consistent case (lowercase recommended).

  • A root node must enclose all other content.

  • All tags must be closed (either with a balancing close tag or as a self-closing tag).

  • All tags must be properly nested.

  • All attribute values must be quoted.

  • Whitespace is ignored by default.

  • Flash doesn’t validate XML by version or Document Type Definition (DTD).

One or two other simple rules apply, and will be covered in the remainder of this chapter, but XML use in Flash is pretty straightforward. ActionScript 3.0 has also gone a long way to simplifying things.

The previous functionality of the XML class has been moved over to the XMLDocument class and included primarily to improve support for legacy projects. Don’t use this outdated technique. The new XML class is used mainly for working with your entire XML data set as a whole, and supporting classes such as XMLList are used to work with specific content. Familiar dot syntax, like the kind used for ActionScript itself to traverse objects, properties, methods, and so on, is now used in place of the verbose familial navigation from prior versions of ActionScript.

16.1 Creating an XML Object

Problem

You want to create an object to hold XML data for parsing.

Solution

Create an instance of the XML class.

Discussion

You have a few ways to populate an instance of the XML class. Firstly, you can add data to an empty instance, as needed. 16.11 Writing XML, discusses this approach. The second approach is to assign data to the instance immediately. ActionScript 3.0 makes this easy because you can type the XML in human-readable form, complete with white space, and carriage returns don’t break the assignment. The following example creates an object, products, which nearly all of the recipes in this chapter use.

var products:XML =
    <root>
        <season quarter="3">Fall</season>
        <whatsnew>
            <promotion>Fall Sale</promotion>
        </whatsnew>
        <books>
            <book>
                <title series="learning">Learning ActionScript 3.0</title>
                <authors>Shupe and Rosser</authors>
            </book>
            <book>
                <title series="cookbook">ActionScript 3.0 Cookbook</title>
                <authors>Lott, Schall, and Peters</authors>
            </book>
            <book>
                <title series="animal">Essential ActionScript 3.0</title>
                <authors>Moock</authors>
            </book>
        </books>
    </root>;

The third method is to start with a string of valid XML, and then pass that to the constructor of the XML class, as seen in the following very concise example— quite handy for dynamic creation of XML starting with a text source (such as user input).

var xmlString:String = "<root><username>J. G. Thirlwell</username></root>"
var xml:XML = new XML(xmlString);

16.2 Loading XML

Problem

You want to load XML from an external document or server.

Solution

Create an instance of the URLLoader class to load the XML, and then create an instance of the XML class with the loaded data.

Discussion

Although the next chapter discusses working with external assets, people most often work with XML in ActionScript by loading XML from a server or external document. As such, the following example demonstrates the basics you need.

To load XML, you must start with an instance of the URLLoader class. This class is used to load text, variables, and binary data. Because the XML must be loaded before it can be parsed, an event listener is commonly used to process the incoming data after the Event.COMPLETE event is dispatched (indicating that the load is complete). Finally, you must process all URLs using a URLRequest, which can then be passed to the load() method seen in the third line of code that follows.

var xmlLoader:URLLoader = new URLLoader();
xmlLoader.addEventListener(Event.COMPLETE, onComplete, false, 0, true);
xmlLoader.load(new URLRequest("store.xml"));

function onComplete(evt:Event):void {
    var xmlData:XML = new XML(evt.target.data);
    trace(xmlData);
}

The onComplete() listener function then converts the loaded data into an XML instance (using the last technique discussed in 16.1 Creating an XML Object), and traces the data to show you a visual result for testing.

Note

Using an instance of the URLRequest class may seem extraneous when simply loading an asset (as opposed to just using a string). However, you see in 16.12 Writing XML with Variables that you can configure the instance for sending data, and the consistent use in all cases is a wonderful hallmark of ActionScript 3.0.

See Also

16.1 Creating an XML Object for creating an XML object.

16.3 Reading an Element Node

Problem

You want to isolate a portion of a larger XML object to work with a single element node.

Solution

Use the familiar dot-syntax object model introduced in ActionScript 3.0 to work with XML, and target an element node.

Discussion

ActionScript 3.0’s implementation of XML lifts a pretty big weight off your shoulders when it comes to parsing data. You no longer need to use a series of sequential methods and/or properties to traverse an XML tree. Instead, you need only walk through nodes using dot syntax similar to the ActionScript document object model with which you’re already familiar.

To begin, examine this chapter’s primary sample XML:

var products:XML =
    <root>
        <season quarter="3">Fall</season>
        <whatsnew>
            <promotion>Fall Sale</promotion>
        </whatsnew>
        <books>
            <book>
                <title series="learning">Learning ActionScript 3.0</title>
                <authors>Shupe and Rosser</authors>
            </book>
            <book>
                <title series="cookbook">ActionScript 3.0 Cookbook</title>
                <authors>Lott, Schall, and Peters</authors>
            </book>
            <book>
                <title series="animal">Essential ActionScript 3.0</title>
                <authors>Moock</authors>
            </book>
        </books>
    </root>;

The first node, the root node, is a requirement of XML. Although its presence is confirmed, it’s basically ignored when it comes to parsing. For this reason, some developers prefer to assign it an obvious name, such as “root” (as in this case) or “wrapper,” to reinforce that they should skip it when referencing content.

So, to reference a node, start with the XML object as a whole, and then continue to add nested children until you get what you want. You’ll learn what to do when you have more than one node with the same name in the same parent tag but for now, look at a simple example. Only one node’s called whatsnew, so that node’s address is products.whatsnew. Tracing that content in the following script reveals that all data contained in that node is referenced:

trace(products.whatsnew);
/*
<whatsnew>
    <promotion>Fall Sale</promotion>
</whatsnew>
*/

Other examples include:

  • books: products.books

  • book: products.books.book

  • title: products.books.book.title

If you wish to store a reference to an element node, its data type is XMLList. This is the class used to work with one or more content nodes of the XML object, and will be discussed in 16.5 Working with Multiple Nodes of the Same Name. Once you have a reference, you can then parse the content of that particular node.

var bks:XMLList = products.whatsnew;
trace(bks.promotion);

16.4 Reading a Text Node

Problem

You want to access text nested within an element node.

Solution

Use the familiar dot-syntax object model introduced in ActionScript 3.0 to work with XML, and use the text() method to target a text node.

Discussion

Reading a text node is essentially the same as reading an element node. However, you should remember one subtlety that. When you read an element node that contains no children (also known as simple content), ActionScript nicely returns that node’s content. The result of reading that node appears to be a String, and even behaves like a String for your convenience. For example, consider the following manipulations of the season element node of this chapter’s sample XML:

trace(products.season);
//Fall;
trace(products.season.charAt(0));
//F

Note that even the String method charAt() functioned correctly when applied to the season node, even though it’s an element. You can verify the node’s element status using the nodeKind() method:

trace(products.season.nodeKind());
//element

This on-the-fly casting is a nice feature when you’re dealing with simple content. You can work with the element or its content, based on your own needs. If, however, you specifically need to work with a text node, you need to take an extra step. One such step is to use the text() method.

trace(products.season.text());
//Fall
trace(products.season.text().nodeKind());
//text

Usually you don’t need this extra step because ActionScript automatically returns the content of an element node, if it has no children. Furthermore, you can’t logically think of complex content (child element nodes) as text, so this characteristic isn’t really a limitation. (This issue may be unintentional, as when HTML tags are interpreted as XML child nodes, but this issue’s discussed in 16.9 Reading HTML or Entities in XML Nodes.)

However, you may still wish to occasionally take the extra step to use the text() method to work with text nodes, because of its main purpose. It was designed to create an XMLList of text nodes, as explained in the following recipe.

See Also

16.3 Reading an Element Node for reading element nodes.

16.5 Working with Multiple Nodes of the Same Name

Problem

You want to easily work through one or more nodes of the same name in one data structure.

Solution

Create an instance of the XMLList class by targeting the desired repeating element.

Discussion

One of the ActionScript 3.0’s XML implementation’s most spectacular features is that it can automatically traverse an XML structure and create a list of all occurrences of a specific node. For clarity of discussion, take another look at this chapter’s sample XML:

var products:XML =
    <root>
        <season quarter="3">Fall</season>
        <whatsnew>
            <promotion>Fall Sale</promotion>
        </whatsnew>
        <books>
            <book>
                <title series="learning">Learning ActionScript 3.0</title>
                <authors>Shupe and Rosser</authors>
            </book>
            <book>
                <title series="cookbook">ActionScript 3.0 Cookbook</title>
                <authors>Lott, Schall, and Peters</authors>
            </book>
            <book>
                <title series="animal">Essential ActionScript 3.0</title>
                <authors>Moock</authors>
            </book>
        </books>
    </root>;

If you look closely, you see that a book node is repeated three times and, thanks to the design of this XML document, each node’s contents are consistent. As you can see, title appears in each of these nodes.

Previously, to get to all title nodes, you had to do a bit of juggling. Most often, you could traverse either up or down the tree storing references each time you reached a title node, or create a copy of the most relevant portion of the XML, and then delete unwanted elements. What a pain. Now, with the magic of ActionScript 3.0, you can automatically create a list of all like nodes:

var bookTitles:XMLList = products.books.book.title;
trace(bookTitles);
/*
<title series="learning">Learning ActionScript 3.0</title>
<title series="cookbook">ActionScript 3.0 Cookbook</title>
<title series="animal">Essential ActionScript 3.0</title>
*/

Since an XMLList instance behaves like an array, you can work with individual nodes in the list.

trace(bookTitles[0]);
//Learning ActionScript 3.0

One of the things you should watch out for, however, is that length, an array property that returns the number of items in the array, is actually a method when you use it on an instance of the XMLList class.

trace(bookTitles.length());
//3

For data typing purposes, note that even a single node is typed as an XMLList instance, because it’s possible for more than one node of the same name to exist.

trace(products.season is XMLList);
//true

Finally, as mentioned in the previous recipe, the text() method creates an XMLList of text nodes (ActionScript’s trace() method doesn’t insert commas into list output):

var titleTxt:XMLList = products.books.book.title.text();
trace(titleTxt);
//Learning ActionScript 3.0ActionScript 3.0 CookbookEssential ActionScript 3.0
trace(titleTxt[0]);
//Learning ActionScript 3.0;

16.6 Reading an Attribute

Problem

You want to read an attribute from an element node.

Solution

Use the attribute (@) operator.

Discussion

Attributes are properties found within a node, just like similar properties found within HTML tags. An example in this chapter’s sample XML is the quarter attribute of the season node.

<season quarter="3">Fall</season>

You can target attributes with the same dot syntax used for element nodes, simply by preceding the attribute name with an at symbol (@).

trace(products.season.@quarter);
//3

As with element and text nodes, you can also create an XMLList of attributes. (ActionScript’s trace() method doesn’t insert commas into list output):

trace(products.books.book.title.@series);
//learningcookbookanimal

Finally, if you have an uncooperative attribute name, such as a name containing hyphens, you can use the attribute() method to specify the desired attribute. Similarly, if you prefer to remain consistent with the use of the attribute operator, then you can use bracket syntax, as the following hypothetical examples show.

simple.example.attribute("hyphenated-name");
simple.example.@["hyphenated-name"];

Both these approaches are akin to similar tasks relevant to array manipulation and, as with arrays, are handy for working with dynamically generated names. For example, you could use a for loop to loop through a series of numbered attributes:

simple.example.attribute("attname" + i);
simple.example.@["attname" + i];

See Also

16.3 Reading an Element Node for reading an element node.

16.7 Finding Content Using Shorthand

Problem

You want to work with content nodes in an XML object without knowing their exact locations.

Solution

Use the descendent (..) or wildcard (*) operators.

Discussion

Sometimes you may want to pull data from separate but similar nodes. For example, you may want to retrieve content from all siblings in a particular node, even if they’re unique. In this case, you can use a wildcard (the asterisk, *) to stand in for the element node name.

The following example creates an XMLList of all text nodes within the first book node of this chapter’s sample XML. First, revisit the XML, reproduced here:

var products:XML =
    <root>
        <season quarter="3">Fall</season>
        <whatsnew>
            <promotion>Fall Sale</promotion>
        </whatsnew>
        <books>
            <book>
                <title series="learning">Learning ActionScript 3.0</title>
                <authors>Shupe and Rosser</authors>
            </book>
            <book>
                <title series="cookbook">ActionScript 3.0 Cookbook</title>
                <authors>Lott, Schall, and Peters</authors>
            </book>
            <book>
                <title series="animal">Essential ActionScript 3.0</title>
                <authors>Moock</authors>
            </book>
        </books>
    </root>;

Note that the child nodes are title and authors. Due to the wildcard, the text from both of these nodes is retrieved.

trace(products.books.book[0].*.text());
//Learning ActionScript 3.0Shupe and Rosser

In fact, the book node itself is an XMLList containing three books. Omitting the bracket and zero index in the preceding script segment returns the title and authors for all three books, easily storable in one XMLList instance, if you want.

The descendent operator, two dots (..), functions in a somewhat similar manner, but stands in for nested levels of nodes. The operator traverses the XML object looking for any specified node, wherever it may be. The following snippet, for example, returns an XMLList of all three titles, even though title isn’t at the root of the XML object. Instead, the first level (books) and second level (book) are both traversed to find title in the third level of the XML structure.

trace(products..title);

See Also

16.3 Reading an Element Node and 16.4 Reading a Text Node for reading element and text nodes.

16.8 Finding Content Using Conditionals

Problem

You want to retrieve one or more nodes based on a specific value.

Solution

Filter content by element or attribute value using logical comparisons.

Discussion

Another ActionScript 3.0 XML gem is the ability to filter content when retrieving it. A simple test, like those in a basic if statement, can be added to the dot syntax address, and only nodes satisfying that test are returned. You just have to wrap the test in parentheses, and then place the entire expression where the original object would have been.

The following examples retrieve single element nodes based first on the value of another element node, and second based on the value of an attribute. For comparison, however, start with the same path to these items, without the conditionals:

//products.books.book.authors
//products.books.book.title.@series

The first path references an XMLList of all authors nodes in all book nodes, and the second creates an XMLList of all series attributes in all title nodes of all book nodes. If you know which specific node you want, then you can use bracket syntax and specify an index. If you don’t know that information, however, or you want to find every occurrence that satisfies a test, you can rely on conditionals. Using the conditionals filters the content, resulting in the return of only one node in each example.

trace(products.books.book.(authors=="Shupe and Rosser"));
/*
<book>
    <title series="learning">Learning ActionScript 3.0</title>
    <authors>Shupe and Rosser</authors>
</book>
*/

trace(products.books.book.title.(@series=="learning"));
//Learning ActionScript 3.0

See Also

16.3 Reading an Element Node for reading an element node and 16.6 Reading an Attribute for reading an attribute.

16.9 Reading HTML or Entities in XML Nodes

Problem

You want to parse an XML object so enclosed XML-valid entities appear correctly, and enclosed HTML isn’t interpreted as XML child nodes.

Solution

Use XML-valid entity encoding or enclose content that could be interpreted as XML within a CDATA tag.

Discussion

If you use characters in your data that are also part of the XML specification, they’ll probably cause errors or unpredictable behavior because they’ll be misinterpreted as part of the XML structure rather than as part of the content. XML has five entities, shown in Table 16-1 in both original and encoded forms.

Table 16-1. The five entities included in the XML specification

Entity

Encoded Form

Notes

<

&lt;

less than

>

&gt;

greater than

&

&amp;

ampersand

'

&apos;

apostrophe

"

&quot;

quotation mark

The following shows how to represent the apostrophe using entity encoding.

//incorrect: <publisher>O’Reilly</publisher>
//correct: <publisher>O&apos;Reilly</publisher>

You can also successfully include XML-invalid text in a text node by using the <![CDATA[ ]]> tag. This structure basically tells the XML parser to ignore everything within its inner brackets, and treat that content like regular text. You can use this structure well when you allow HTML tags in an XML text node. XML nodes are bounded by the < and > signs just like HTML tags are, so the HTML is thought to be one or more nested XML nodes. The following example includes both the normal apostrophe and the HTML underline tags without entity encoding, because it’s wrapped within a CDATA tag.

//incorrect: <publisher><u>O’Reilly</u></publisher>
//correct: <publisher><![CDATA[<u>O’Reilly</u>]]></publisher>

You can encode the < and > signs too, of course, but it can be quite tedious. The following example adds a publisher node to all book nodes of this chapter’s sample XML, and demonstrates the three examples of including XML-invalid content in text nodes. The last part of the script dynamically creates a text field, and then populates it with HTML to show that the nested underline tags aren’t misinterpreted.

var products:XML =
    <root>
        <season quarter="3">Fall</season>
        <whatsnew>
            <promotion>Fall Sale</promotion>
        </whatsnew>
        <books>
            <book>
                <title series="learning">Learning ActionScript 3.0</title>
                <authors>Shupe and Rosser</authors>
                <publisher>O&apos;Reilly</publisher>
            </book>
            <book>
                <title series="cookbook">ActionScript 3.0 Cookbook</title>
                <authors>Lott, Schall, and Peters</authors>
                <publisher><![CDATA[<u>O'Reilly</u>]]></publisher>
            </book>
            <book>
                <title series="animal">Essential ActionScript 3.0</title>
                <authors>Moock</authors>
                <publisher>&lt;u&gt;O&apos;Reilly&lt;/u&gt;</publisher>
            </book>
        </books>
    </root>;

var txtFld:TextField = new TextField();
addChild(txtFld);
txtFld.type = TextFieldType.DYNAMIC;
txtFld.htmlText = products.books.book[1].publisher;

16.10 Deleting XML

Problem

You want to remove nodes from an XML object.

Solution

Use the delete operator.

Discussion

Sometimes it’s easier to delete unwanted XML content than to reference extensive amounts of desired content in an XML instance. In those cases, you can use the delete operator to delete an element, text node, or attribute. The syntax for identifying the XML object in question is the same as referencing it, and the delete operator then precedes this path.

delete products.whatsnew;

This process is also useful when writing XML, which is discussed in the next recipe.

See Also

16.11 Writing XML for writing content.

16.11 Writing XML

Problem

You want to dynamically build an XML object at runtime.

Solution

Adapt XML reading techniques to writing content, and consider adding the use of methods such as appendChild(), prependChild(), and insertChildAfter().

Discussion

You’ll often find it convenient to write XML, either for use within the same SWF file, transmission to a database, or even to save to an external file. Most of the tasks you need to write XML are identical to reading the same XML object, except that you find the path to the object on the left side of an equal sign.

To demonstrate each of the major writing techniques, this recipe adds new content to the ongoing sample used throughout this chapter. Excerpts from the XML, enclosed in comments to separate the resulting XML from the ActionScript, demonstrate these techniques. At the end of the recipe, the new content is shown fully assembled. This recipe begins by using writing techniques similar to those used in reading XML.

Writing an element node without any additional qualifying information places the node at the end of the XML object. Here, you can see that a shirts node is added to the end of the object, just before the close of the root node. (The ellipsis at the start of the comment indicates that output has been removed for the sake of brevity.)

products.shirts = <shirts />;
/*
    ...
    </books>
    <shirts/>
</root>
*/

Writing a text node simply requires that you add text as a child to an existing element node. (You can also add both element and text nodes simultaneously, as demonstrated in a moment.)

products.shirts.tshirt = "Lemur";
/*
<shirts>
    <tshirt>Lemur</tshirt>
</shirts>
*/

Adding an attribute requires only the target node and content.

products.shirts.tshirt.@size = "XL";
/*
<tshirt size="XL">Lemur</tshirt>
*/

You can also write content using methods. The appendChild() method is like the first example in this recipe, in that it adds the child to the end of the node to which the method’s attached.

products.shirts.appendChild(<tank />);
/*
<shirts>
    <tshirt size="XL">Lemur</tshirt>
    <tank/>
</shirts>
*/

The prependChild() method offers new functionality by adding the new node to the beginning of the node to which the method is attached.

products.shirts.prependChild(<longsleeve />);
/*
<shirts>
    <longsleeve/>
    <tshirt size="XL">Lemur</tshirt>
    <tank/>
</shirts>
*/

Finally, the insertChildAfter() method lets you add a node after any specific node. That is, rather than automatically adding to the end of the node to which the method is attached, it’s added immediately after the sibling node specified in the method’s first parameter.

products.shirts.insertChildAfter(products.shirts.tshirt, <onesie/>);
/*
<shirts>
    <longsleeve/>
    <tshirt size="XL">Lemur</tshirt>
    <onesie/>
    <tank/>
</shirts>
*/

Including the delete process from 16.10 Deleting XML, the altered products XML object should now look like this:

<root>
    <season quarter="3">Fall</season>
    <books>
        <book>
            <title series="learning">Learning ActionScript 3.0</title>
            <authors>Shupe and Rosser</authors>
        </book>
        <book>
            <title series="cookbook">ActionScript 3.0 Cookbook</title>
            <authors>Lott, Schall, and Peters</authors>
        </book>
        <book>
            <title series="animal">Essential ActionScript 3.0</title>
            <authors>Moock</authors>
        </book>
    </books>
    <shirts>
        <longsleeve/>
        <tshirt size="XL">Lemur</tshirt>
        <onesie/>
        <tank/>
    </shirts>
</root>

See Also

16.3 Reading an Element Node, 16.4 Reading a Text Node, and 16.6 Reading an Attribute for relevant XML reading techniques, as well as 16.10 Deleting XML for deleting XML content.

16.12 Writing XML with Variables

Problem

You want to use variables, or other dynamic data, when writing XML.

Solution

Wrap dynamic content in braces ({}).

Discussion

If you review 16.1 Creating an XML Object, which discussed creating an XML object, it’s probably not much of a stretch to imagine using a variable to write dynamic content in the second method, because you could perform any String operation on the content before sending it to the constructor of the XML class. Here’s an example adapted from 16.1 Creating an XML Object:

var uName:String = "Clint Ruin"

var xmlString:String = "<root><username>" + uName + "</username></root>"
var xml:XML = new XML(xmlString);

However, another technique is not as obvious. You can also use variables to populate XML content node by node, including element nodes, text nodes, and attributes. To do so, you need only enclose the variable in braces to prevent the XML class parser from seeing the variable name as an XML object name.

Adapting the preceding code snippet, you would use the uName variable this way to write a text node:

var uName:String = "Clint Ruin";
var userxml:XML =
    <root>
        <username>{uName}</username>
    </root>;

Here’s an expanded example demonstrating the addition of an element node, an attribute, and an attribute value. It is certainly unlikely that you would need to do all this dynamically. With this approach, you typically add text nodes or attribute values. However, this example shows that you can dynamically create any of these XML objects.

var uName:String = "Clint Ruin";
var reg:XML = <registered/>;
var psswrd:String = "DJ_OTESFU";
var versionAttr:String = "current";

var user:XML =
    <root>
        <username>{uName}</username>
        {reg}
        <password {versionAttr}={psswrd}/>
    </root>;

trace(user);
/*
<root>
  <username>J. G. Thirlwell</username>
  <registered/>
  <password current="DJ_OTESFU"/>
</root>
*/

See Also

16.1 Creating an XML Object for creating an XML object.

16.13 Sending and Loading XML

Problem

You want to send XML to a server, and process XML received from a response.

Solution

Configure a URLRequest instance, and use the load() method of the URLLoader class.

Discussion

XML is ideal for transferring data to and from a server. This very basic example sends XML to a PHP script that saves a file to the server, and then returns an XML object in response. This example is taken from Learning ActionScript 3.0 by Rich Shupe and Zevan Rosser (O’Reilly), and used by permission.

The first block of the script creates an XML object from a string, as shown in 16.1 Creating an XML Object. The second block creates another XML object to contain the XML returned from the server after submission.

The third block creates a URLRequest instance, as in 16.2 Loading XML but, this time, configures the instance for sending as well as loading. It specifies the server script location, attaches the XML to the data property, sets the contentType of the submission to “text/xml,” and then specifies the POST method for transmission.

The fourth block creates an instance of the URLLoader, which you also saw in 16.2 Loading XML, as well as adds event listeners for the completion of the response loading, and for the unfortunate possibility of an IO error—both of whose functions are explained after the script.

ActionScript

var respTxt:TextField = new TextField();
respTxt.type = TextFieldType.DYNAMIC;
addChild(respTxt);

var xmlString:String = "<?xml version='1.0' encoding= ¬
     'ISO-8859-1'?><root><value>Sally</value><value>Claire</value></root>"
var kids:XML = new XML(xmlString);

var xmlResponse:XML;

var xmlURLReq:URLRequest = new URLRequest(¬
     "http://<your domain>/savexml.php");
xmlURLReq.data = kids;
xmlURLReq.contentType = "text/xml";
xmlURLReq.method = URLRequestMethod.POST;

var xmlSendLoad:URLLoader = new URLLoader();
xmlSendLoad.addEventListener(Event.COMPLETE, onComplete, false, ¬
     0, true);
xmlSendLoad.addEventListener(IOErrorEvent.IO_ERROR, onIOError, false, ¬
     0, true);
xmlSendLoad.load(xmlURLReq);

function onComplete(evt:Event):void {
    try {
        xmlResponse = new XML(evt.target.data);
        respTxt.text = xmlResponse.status;
        removeEventListener(Event.COMPLETE, onComplete);
        removeEventListener(IOErrorEvent.IO_ERROR, onIOError);
    } catch (err:TypeError) {
        respTxt.text = "An error occured when communicating ¬
             with server:
" + err.message;
    }
}

function onIOError(evt:IOErrorEvent):void {
    respTxt.text = "An error occurred when attempting to load ¬
         the XML.
" + evt.text;
}

The last two blocks of the ActionScript are the listener functions. When the response is completely loaded, onComplete() is triggered. This function attempts to create an XML object from the response received, put the status node into a text field, and remove both listeners as an example of good memory management. (This example assumes the data will be sent to the server only once, so you won’t need the listeners later.) If XML isn’t returned successfully from the server, then an alternate message is placed in the text field. A similar error message is placed in the field in the event of an IO error.

Although explaining PHP in depth is beyond the scope of this book, the following simple script is the server component of the example. It receives the incoming data, writes it to a file called data.txt in the same directory as the PHP script, and then sends back one of two messages, both formatted as an XML compliant string with the message wrapped in a status node. If successful, the script sends back “File saved.” If not successful, the script sends back one possible explanation for the error, “PHP write error. Check permissions.”

PHP

<?php

if (isset($GLOBALS["HTTP_RAW_POST_DATA"])){
    $data = $GLOBALS["HTTP_RAW_POST_DATA"];

    $file = fopen("data.txt","w");
    fwrite($file, $data);
    fclose($file);

    if (!$file) {
        echo("<root><status>PHP write error. Check ¬
             permissions.</status></root>");
    } else {
        echo("<root><status>File saved.</status></root>");
    }
}

?>

You certainly don’t have to save XML files to a server to use the send and load feature. In fact, you’re much more likely to send XML to a database or other server script such as a login mechanism. However, this tidy example demonstrates the requisite features, and you can take it from here.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.78.237