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.
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);
Create an instance of the URLLoader
class to load the XML, and then
create an instance of the XML
class
with the loaded data.
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.
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.
16.1 Creating an XML Object for creating an XML object.
Use the familiar dot-syntax object model introduced in ActionScript 3.0 to work with XML, and target an element node.
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);
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.
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.
16.3 Reading an Element Node for reading element nodes.
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;
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];
16.3 Reading an Element Node for reading an element node.
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);
16.3 Reading an Element Node and 16.4 Reading a Text Node for reading element and text nodes.
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
16.3 Reading an Element Node for reading an element node and 16.6 Reading an Attribute for reading an attribute.
You want to parse an XML object so enclosed XML-valid entities appear correctly, and enclosed HTML isn’t interpreted as XML child nodes.
Use XML-valid entity encoding or enclose content that could be interpreted as XML within a CDATA tag.
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.
Entity | Encoded Form | Notes |
|
| less than |
|
| greater than |
|
| ampersand |
|
| apostrophe |
|
| quotation mark |
The following shows how to represent the apostrophe using entity encoding.
//incorrect: <publisher>O’Reilly</publisher> //correct: <publisher>O'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'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><u>O'Reilly</u></publisher> </book> </books> </root>; var txtFld:TextField = new TextField(); addChild(txtFld); txtFld.type = TextFieldType.DYNAMIC; txtFld.htmlText = products.books.book[1].publisher;
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.
16.11 Writing XML for writing content.
Adapt XML reading techniques to writing content, and consider
adding the use of methods such as appendChild()
, prependChild()
, and insertChildAfter()
.
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>
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.
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> */
16.1 Creating an XML Object for creating an XML object.
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.
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 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.