phpXML Home | XML Test Sandbox | RSS Feed Example | Flash-to-PHP Example

ones&zeros phpXML.class.php

    - A lightweight PHP-based XML parser and generator
Version 1.1 - 3 April 2007
Written by Andy Frey (andy AT onesandzeros DOT biz)
ones&zeros (http://onesandzeros.biz) - Phoenix, AZ
Copyright © by Andy Frey.

License of use: This code may only be used by permission from Andy Frey (andy AT onesandzeros DOT biz or http://onesandzeros.biz). This code may not be altered in any way without permission. For bug reporting and suggestions for features, please visit the website at http://onesandzeros.biz/xml/.

Abstract

This PHP object is a very lightweight XML parser and generator. It does not validate XML, so be sure that you're sending it good code. While it may be used for larger files, it was really designed to handle Flash-to-PHP script communications. In Flash, it is very simple for the programmer to parse and generate XML using Actionscript. On the PHP side, I found no simple little one-script utilities or classes or functions that could do it easily for me. So, about a week's worth of hacking got me this. I hope you find it useful.

The object can be used in two "directionns:" It can parse incoming XML code from a file, a URL, or a string. It can also be used to put together an XML document using easy OOP coding, modeled after the moethods in Flash MX 2004 Actionscript.

Technically, certain elements, like the DOCTYPE and ENTITY elements, for instance, should be put in specialty nodes, perhaps. I dunno. If you want my opinion on those beasts, email me and ask me. This XML parsing/generating class library is meant for simply moving XML back and forth between your applications and pulling in and parsing RSS feeds. If you're looking for a world-class parser that handles all those (IMHO) bloating style and modularity tags, you're using the wrong class. This neato little class does it's thing very well on nice and clean, well-formed, pure XML. But, if you run across XML (especially from RSS feeds or fat Microsoft bloat applications), this should still work. It just won't preserve those whacky <!DOCTYPE> and <!ENTITY> and <!ELEMENT> tags and stuff.

Addendum to Author's Note/Opinion: Technically, there should be routines in this class that output the above mentioned tags, but there are not. This was designed to be a lightweight XML class. Its main purpose in life is to be used as a way to decode and encode XML between your own applications. As I mentioned above, I wrote this mainly to use as a companion to my Flash-to-PHP communications. In that endeavor, it will save you time and headaches. We have been using this class heavily in a very busy production environment and the latest revision has been working flawlessly, I'm happy to report.

To see the class at work, look at this sample of RSS feeds: rss-sample.php

Get To It! Examples of Parsing XML

Now, if you're like me (and I know I am), you like to get right to the example code to get a quick idea of whether or not a library or class is going to meet your needs. Here are examples of using the phpXML class for parsing and building XML documents.

$xml = new phpXML( "<mainTag><firstChild><subTag>Value in " .
"subTag</subTag></firstChild><secondTag parameterOne="a " .
"value" /></mainTag>" );
$xml->toString();

This will output the code from the string, minus comments and possibly with cleaner formatting (throws away extra whitespace and such):

<mainTag><firstChild><subTag>Value in subTag</subTag></firstChild><secondTag [linebreak]
parameterOne="a value"/></mainTag>

So, given just that little tidbit, you realize now that you could very easily open up a file or URL with file_get_contents() and pass the contents into the phpXML class instantiation.

There's not much you can do to XML to make it "pretty," but I give you 4 options for formatting the code that is generated with the toString() method. Not exactly sure how useful each one is, but you have them at your disposal. First, if you do nothing with it (give it no parameters), it outputs the XML with whitespace formatting added by default. It puts X number of tabs in front of an opening tag, depending on how deep it is in the XML tree. If you would like to override the tab character for indentation and provide the number of spaces to indent instead, just pass an integer to tell toString() how many space to use in-place of the tab character. If you would like to use your own indentation character string, just pass the string of characters and they will be used instead of a tab character. If you would rather get your XML code wihtout any whitespace formatting, pass the boolean value of false and there will be no neato formatting.

$xml->toString(); // will indent with the tab character and append newlines
$xml->toString( false ); // not have indentation or newlines; allXMLcodewillruntogether ;)
$xml->toString( 4 ); // will indent with 4 spaces instead of the tab character and append a newline
$xml->toString( "...." ); // will indent with 4 periods instead of the tab character and append a newline

This will doctor up the XML output with 4 spaces for each level of indentation in the tags and it will append newline characters after each closed tag, like this:

<mainTag>
	<firstChild>
		<subTag>Value in subTag</subTag>
	</firstChild>
	<secondTag parameterOne="a value"/>
</mainTag>

It may or may not look completely correct because of your browser, but you get the idea.

Now, let's say that above code is in the file, "sample.xml" in the same directory as your script. Just instantiate the phpXML class like this:

$xml = new phpXML();
$xml->load( "sample.xml" );
$xml->toString( 2 );

This will output the exact same thing as above. The only difference was that we instantiated an "empty" XML doc, then loaded a file. You can do the exact same thing for a URL, like if you were going to read an RSS feed into your script:

$xml = new phpXML();
$xml->load( "http://onesandzeros.biz/rss/jokes4today.xml" );
$xml->toString( );

Examples of Building XML

If you'd like to use the phpXML and phpXMLNode classes to build an XML document, it's pretty straightforward. Sometimes, keep in mind that it might be easier to jsut output your data with tags around it using echo or string concatenation. Using this interface may be easy programmatically, but might add overhead to what could otherwise just be a bunch of echos in loops. Just my opinion.

So, let's start out with an idea of what we need our final output to create, so here is what the file will look like:

<addressBook>
	<friend name="Andy Frey" website="onesandzeros.biz" city="Mesa" state="AZ">
		Here are some notes about Andy. He's a nice guy.
	</friend>
	<friend name="John Smith " website="smithsite.org" city="Tampa" state="FL">>
		John is looking to change his name to something more enigmatic.
	</friend>
</addressBook>

The phpXML class library has one class that's really the meat of the whole thing: phpXMLNode. phpXMLNode is the class has several properties that are of importance: name, attributes, value, and childNodes. When you instantiate the phpXML class, you're actually intantiating a super class of phpXMLNode, if you're wondering why you aren't just intantiating phpXMLNode to create a tree. The parsing and such is done in the phpXML class. The phpXMLNode class needs a parent to watch out for it and that's what the phpXML class is for. :)

The name property contains the name fo the XML tag (which translates to a node during parsing).

The attributes array is an associative array of the attributes listed after the tag name between the < and >. In the example XML code above, the "friend" tags have four attributes: name, website, city, and state. The associative array attributes for that node would look like this if printed with PHP's print_r():

Array
(
	[name] => Andy Frey
	[website] => onesandzeros.biz
	[city] => Mesa
	[state] => AZ
)

The value is simply any text that was between an open tag and a close tag. In the example above, the text between the <friend...> and </friend> tags is the value property of that node.

The chlidNodes property is an array of phpXMLNode objects, if there are indeed children of the node in question. For instance, the nodes of your XML document can be retrieve by recursing down through the $xml->childNodes array, which is all the toString() method is doing.

So, let's get to creating the XML tree using the OOP of phpXML(). I'm just going to list the code out for you and you can read the comments to get the idea:

$xml = new phpXML();
// first, create a containing tag/node
$xmlAddrBook = new phpXMLNode( "addressBook" );
// append a friend tag node under the addressBook node 
$xml->appendChild(
	// this creates a node on-the-fly 
	new phpXMLNode(
		// the name of the tag 
		"friend",
		// tag attributes (you can pass an associative array like this for the attributes) 
		array( 
			"name"=>"Andy Frey", 
			"website"=>"onesandzeros.biz", 
			"city"=>"Mesa" 
			"state"=>"AZ" 
		), 
		// the value that goes between the "friend" tags 
		"Here are some notes about Andy. He's a nice guy." 
	) 
);
// append another friend tag node under the addressBook tag node
$xmlAddrBook->appendChild(
	new phpXMLNode(
		"friend",
		// OR, you can pass a string of parameter name/value pairs in this format:
		// nameOfParameter="value of parameter" (quotes should be slashed, of course) 
		"name=\"John Smith\" website=\"smithsite.org\" city=\"Tampa\" state=\"FL\"", 
		"John is looking to change his name to something more enigmatic." 
	) 
);
// now, add the addressBook tag and its children to the xml doc 
$xml->appendChild( $xmlAddrBook );
// output the XML code all prettied up with 4-space indenting 
echo $xml->toString(); 

Flash MX 2004 Notes

Coming very shortly: Full code examples for sending and receiving XML between Flash and PHP and back.

Technical Note:

There have been many solutions to receiving XML from Flash. The best I've seen (or, at least, the easiest to get from the POST variables, is the following idea from an unknown author on the Macromedia Flash forums.

As an alternative to "print file_read_contents('php://input') ;" and "always_populate_raw_post_data = On", set the sending phpXML object's xmlDecl to "xml=".

In Flash:

my_xml.xmlDecl = "xml=";

When using PHP, this creates a key in the $HTTP_POST_VARS/$_POST arrays with which you can access the incoming xml.

In PHP:

$xmlCode = $_POST['xml'];

Then, of course, to send the response back to Flash, in the case of a Flash sendAndLoad(), you just echo out your XML code, sending a header( "Content-type: text/xml" ) before it.


 

Classes, Methods and Properties


phpXMLNode class

This is really the workhorse of the package. The XML class extends the phpXMLNode class because it becomes the "root" of the tree and then it adds parsing functionality and document-level features, otherwise, the XML class is a hyped-up phpXMLNode object.

The childNodes property of any phpXMLNode is, as the name implies, a list (array) of any nodes that are considered children to the node in question. As such, there are some built-in helpful methods that take advantage of some of the cool PHP array functions, such as reset/current (used together in the method firstChild), next, prev, and end.

Properties:

name : string   The name of the tag that this node represents

attributes : array   An associative array of the attributes from the open tag, if it had attributes.

value : string   The text data that is between the open and close tags, if any

childNodes : array   Array of any child nodes to this node (which, themselves, could have children, so the tree needs to be walked to get all children, of course)

useCDataTags : boolean   This determines whether or not CDATA tags are output around the value of this node when the toString() method is called

Methods:

phpXMLNode() : Constructor

Description:

This is the class for phpXMLNodes in your XML document.

Parameters:

[none passed]   If you pass nothing to the constructor, the phpXMLNode is initialized with all properties as blank.

name : string   Name of the node

attributes : string   You can pass attributes in a string as pairs of names = "values" separated by spaces, for example:
    "firstName=\"Andy\" lastName=\"Frey\""

attributes : array   You can also pass attributes as an associative array, for example:
    array( "firstName"=>"Andy", "lastName"=>"Frey" )

value : string   The text value to be placed between the open and closing tags of this node

useCData : boolean   Pass a true value to output <![CDATA[...]]> tags around the value of the node.

Returns:

phpXMLNode : The newly instantiated phpXMLNode object

Notes:

When you call the constructor and you pass any of the parameters, you're actually calling an internal initializer and then the create() method.

create( $name [, $attributes | NULL [, $value | NULL [, $useCData ] ] ] ) : Void

Description:

Populates the properties of this phpXMLNode object with given parameters.

Parameters:

name : string    Name of the node. You must pass AT LEAST this parameter to properly create the node.

attributes : string | array   You can pass attributes in a string as pairs of names = "values" separated by spaces:
    "firstName=\"Andy\" lastName=\"Frey\""
               Or, you can also pass attributes as an associative array:
    array( "firstName"=>"Andy", "lastName"=>"Frey" )

value : string   The text value to be placed between the open and closing tags of this node

useCData : boolean   Pass a true value to output <![CDATA[...]]> tags around the value of the node.

Returns:

nothing

setName( $nameOfTag ) : Void

Description:

Takes a string parameter to set the name property of the node.

Parameters:

valueOfTag : string    The name to be assigned the tag

Returns:

nothing

setValue( $valueOfTag ) : Void

Description:

Takes a single string and sets the value property of the node.

Parameters:

valueOfTag : string    The text to be assigned between the opening and closing tags

Returns:

nothing

appendChild( $phpXMLNode ) : Void

Description:

Adds child nodes to the phpXMLNode object.

Parameters:

phpXMLNode : phpXMLNode    The node to add to the childNodes array

Returns:

nothing

firstChild() : phpXMLNode | boolean

Description:

Returns the first child node.

Parameters:

none

Returns:

phpXMLNode : First child node from the childNodes array
OR
boolean : false if it cannot get the first child node.

nextChild() : phpXMLNode | boolean

Description:

Returns the next child node from the childNodes array.

Parameters:

none

Returns:

phpXMLNode : The next child node in the childNodes array
OR
boolean : false if it cannot get the next child node.

prevChild() : phpXMLNode | boolean

Description:

This method returns the previous child node in the childNodes array or true if it cannot.

Parameters:

none

Returns:

phpXMLNode : The previous child node in the childNodes array
OR
boolean : false if it cannot get the previous child node.

lastChild() : phpXMLNode | boolean

Description:

This method returns the last child node in the childNodes array or true if it cannot.

Parameters:

none

Returns:

phpXMLNode : The last child node in the childNodes array
OR
boolean : false if it cannot get the last child node.

findChildByName( $tagName ) : phpXMLNode | boolean

Description:

Finds the first tag by the name of tagName.

Parameters:

tagName : string    Name of tag to search for

Returns:

phpXMLNode : The first child node in the childNodes array whose name matches the parameter
OR
boolean : false if it cannot find a matching child node.

getAllByName( $tagName ) : array of phpXMLNode | boolean

Description:

Returns an array of nodes that match tagName and is recrusive, so it searches all child nodes, as well.

Parameters:

tagName : string    Name of tags to search for

Returns:

phpXMLNode : The first child node in the childNodes array whose name matches the parameter
OR
boolean : false if it cannot find any matching child nodes.

getAttribute( $attributeName ) : string | boolean

Description:

Returns the attribute string value for the attribute named in the parameter.

Parameters:

attributeName : string    Name of attribute for which you'd like the value

Returns:

string : The value of the parameter give in the parameter
OR
boolean : false if it cannot find a matching parameter.

setAttribute( $attributeName, $attributeValue ) : void

Description:

Sets the attribute string value for the attribute named.

Parameters:

attributeName : string    Name of attribute for which you'd like the value

attributeValue : string    Name of attribute for which you'd like the value

Returns:

nothing

hasChildren() : bolean

Description:

This method returns true if there are children, other wise it returns false.

Parameters:

none

Returns:

boolean : true if this node has child nodes, false if it does not.

childCount() : number

Description:

This method returns of child nodes for this node.

Parameters:

none

Returns:

number : Number of child nodes for this node

toString( [ $indentation ] ) : string

Description:

This produces a string containing the XML code of the node and all of its children.

Parameters:

[pass nothing]    Pass nothing to this method and it will output the XML code with whitespace formatting (newlines and tab characters) making it more readable for human consumption.

indentation : number    Pass a numeric value, the indentation will use indentation number of space characters to indent.

indentation : string    If you pass a string value, the indentation will use the string you passed in "recursion-level" of times to indent. That is, if a node is three levels deep into the tree, the toString() method will insert two copies of your indentation string before it.

indentation : bolean    If you pass a boolean value, false will tell toString() to NOT use formatting, which will cause all the XML code to be run together. If you pass true, default whitespace formatting takes place. Passing true is the same as not passing any parameters at all.

Returns:

string : The XML code representation of this XML node and its children.

write( $filename ) : boolean

Description:

This method attempts to write the XML code of the document out to the filename given.

Parameters:

filename : string    Name of file to which XML code will be written (using the toString() method, actually).

Returns:

boolean : false if it could not write the file.

phpXML class

The phpXML class extends the phpXMLNode class. It is the "root" of the XML tree (or document). It does the heavy first-pass parsing and uses the phpXMLNode to work on individual node parsing.

Document-level features are handled by the phpXML class, of course. Document-wide attributes, such as the XML version, encoding, and miscellaneous specialty tag info is store at the XML class level, not in a node.

The childNodes property of any phpXMLNode is, as the name implies, a list (array) of any nodes that are considered children to the node in question. As such, there are some built-in helpful methods that take advantage of some of the cool PHP array functions, such as reset/current (used together in the method firstChild), next, prev, and end.

Properties:

version : string   The XML version this document is set to (usually "1.0"). Blank by default.

encoding : array   Encoding for this document, such as, "iso-8859-1". Also, blank by default.

docType : array   If a parsed XML document has the <!DOCTYPE...> tag, this array contains it and any element tags contained within it. This will not be output if you invoke the toString() method, however. It's stored, I suppose, for future use or functionality.

parseTime : number   This allows you to see how quickly the class parsed the XML code you sent it. The timer starts after the loading is complete and stops when the parse has a complete heirarchy of XML nodes and document properties.

Methods:

phpXML( [ $xmlCode ] ) : Constructor

Description:

This is the constructor for the XML document. Behind the scenes, since this is actually an phpXMLNode() extended, it does call the initialization for an phpXMLNode() object and sets its name property to "rootNode".

Parameters:

xmlCode : string    You can pass a string of XML code right into the constructor on instantiation and it will parse the code and the document tree will be instantly avilable to your program.

Returns:

XML : A new XML() object.

parseXML( $xmlCode ) : void

Description:

This will parse the XML code you pass into it and populate the document with the resulting tree of phpXMLNode() objects.

Parameters:

xmlCode : string    A string of XML code.

Returns:

nothing

load( $filename | $url ) : boolean

Description:

This will load XML code from either a file or a URL, parse the XML code, then populate the document with the resulting tree of phpXMLNode() objects.

Parameters:

filename : string    A file path from which to retrieve the XML code to parse.

url : string    A URL from which to retrieve the XML code to parse.

Returns:

boolean : true if file or URL was loaded, false if it was not.

toString( [ $indentation ] ) : string

Description:

This produces a string containing the XML code of the document.

Parameters:

[pass nothing]    Pass nothing to this method and it will output the XML code with whitespace formatting (newlines and tab characters) making it more readable for human consumption.

indentation : number    Pass a numeric value, the indentation will use indentation number of space characters to indent.

indentation : string    If you pass a string value, the indentation will use the string you passed in "recursion-level" of times to indent. That is, if a node is three levels deep into the tree, the toString() method will insert two copies of your indentation string before it.

indentation : bolean    If you pass a boolean value, false will tell toString() to NOT use formatting, which will cause all the XML code to be run together. If you pass true, default whitespace formatting takes place. Passing true is the same as not passing any parameters at all.

Returns:

string : The XML code representation of this XML node and its children.

getParseTime() : number

Description:

This method returns the number of seconds it took to parse the XML code for this XML document.

Parameters:

none

Returns:

number : Number of seconds it took to execute parsing of XML code

getXMLInfo() : string

Description:

This method returns the XML document version and encoding in a pre-formatted string.

Parameters:

none

Returns:

string : Pre-formatted XML document info