Commits

nate  committed 033ced9

Changing order of XML class defs (Ticket #2572)

git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@50983807eeeb-6ff5-0310-8944-8be069107fe0

  • Participants
  • Parent commits 02cf8e3

Comments (0)

Files changed (1)

File cake/libs/xml.php

 uses('set');
 
 /**
- * XML handling.
+ * XML node.
  *
- * Operations on XML data.
+ * Single XML node in an XML tree.
  *
  * @package    cake
  * @subpackage cake.cake.libs
  * @since      CakePHP v .0.10.3.1400
  */
-class XML extends XMLNode {
-
+class XMLNode extends Object {
 /**
- * Resource handle to XML parser.
+ * Name of node
  *
- * @var resource
+ * @var string
  */
-	var $__parser;
+	var $name = null;
 /**
- * File handle to XML indata file.
+ * Value of node
  *
- * @var resource
+ * @var string
  */
-	var $__file;
+	var $value;
 /**
- * Raw XML string data (for loading purposes)
+ * Attributes on this node
  *
- * @var string
+ * @var array
  */
-	var $__rawData = null;
-
+	var $attributes = array();
 /**
- * XML document header
+ * This node's children
  *
- * @var string
+ * @var array
  */
-	var $__header = null;
-
+	var $children = array();
 /**
- * XML document version
+ * Reference to parent node.
  *
- * @var string
+ * @var XMLNode
  */
-	var $version = '1.0';
-
+	var $__parent = null;
 /**
- * XML document encoding
+ * Constructor.
  *
- * @var string
+ * @param string $name Node name
+ * @param array  $attributes Node attributes
+ * @param mixed  $value Node contents (text)
  */
-	var $encoding = 'UTF-8';
+	function __construct($name = null, $attributes = array(), $value = null, $children = array()) {
+		$this->name = $name;
+		$this->attributes = $attributes;
+		$this->value = $value;
 
+		$c = count($children);
+		for ($i = 0; $i < $c; $i++) {
+			if (is_a($children[$i], 'XMLNode') || is_a($children[$i], 'xmlnode')) {
+				$this->append($children[$i]);
+			} elseif (is_array($children[$i])) {
+				$cName = '';
+				$cAttr = $cChildren = array();
+				list($cName, $cAttr, $cChildren) = $children[$i];
+				$node = new XMLNode($name, $cAttr, $cChildren);
+				$this->append($node);
+				unset($node);
+			} else {
+				$child = $children[$i];
+				$this->append($child);
+				unset($child);
+			}
+		}
+	}
 /**
- * Constructor.  Sets up the XML parser with options, gives it this object as
- * its XML object, and sets some variables.
+ * Gets the XML element properties from an object
  *
- * @param string $input
+ * @param object $object
+ * @return array
  */
-	function __construct($input = null, $options = array()) {
-		parent::__construct('root');
-		$this->__parser = xml_parser_create_ns();
+	function __objectToNode($object) {
 
-		xml_set_object($this->__parser, $this);
-		xml_parser_set_option($this->__parser, XML_OPTION_CASE_FOLDING, 0);
-		xml_parser_set_option($this->__parser, XML_OPTION_SKIP_WHITE, 1);
+		if (is_array($object)) {
+			$objects = array();
+			foreach ($object as $obj) {
+				$objects[] = $this->__objectToNode($obj);
+			}
+			return $objects;
+		}
 
-		$this->children = array();
+		if (isset($object->__identity__) && !empty($object->__identity__)) {
+			$name = $object->__identity__;
+		} elseif (isset($object->name) && $object->name != null) {
+			$name = $object->name;
+		} else {
+			$name = get_class($object);
+		}
+		if ($name != low($name)) {
+			$name = Inflector::underscore($name);
+		}
 
-		if($input != null) {
-			$vars = null;
-			if (is_string($input)) {
-				$this->load($input);
-			} elseif (is_array($input)) {
-				$vars = $this->__objectToNode(Set::map($input));
-			} elseif (is_object($input)) {
-				$vars = $this->__objectToNode($input);
+		if (is_object($object)) {
+			$attributes = get_object_vars($object);
+		} elseif (is_array($object)) {
+			$attributes = $object[$name];
+			if (is_object($attributes)) {
+				$attributes = get_object_vars($attributes);
 			}
+		}
 
-			if ($vars != null) {
-				$this->children = $vars;
-			}
+		$children = array();
+		$attr = $attributes;
 
-			if (!is_array($this->children)) {
-				$this->children = array($this->children);
+		foreach ($attr as $key => $val) {
+			if (is_array($val)) {
+				foreach ($val as $i => $obj2) {
+					$children[] = $this->__objectToNode($obj2);
+					unset($attributes[$key]);
+				}
+			} elseif (is_object($val)) {
+				$children[] = $this->__objectToNode($val);
+				unset($attributes[$key]);
 			}
 		}
+		unset($attributes['__identity__']);
 
-		foreach ($options as $key => $val) {
-			switch ($key) {
-				case 'version':
-					$this->version = $val;
-				break;
-				case 'encoding':
-					$this->encoding = $val;
-				break;
+		$node = new XMLNode($name, $attributes, null, $children);
+		return $node;
+	}
+/**
+ * Sets the parent node of this XMLNode
+ *
+ * @return XMLNode
+ */
+	function setParent(&$parent) {
+		$this->__parent =& $parent;
+	}
+/**
+ * Returns a copy of self.
+ *
+ * @return XMLNode
+ */
+	function cloneNode() {
+		return $this;
+	}
+/**
+ * Append given node as a child.
+ *
+ * @param XMLNode $child
+ */
+	function &append(&$child) {
+		if (is_object($child)) {
+			$this->children[] =& $child;
+		} elseif (is_string($child)) {
+			$attr = array();
+			if (func_num_args() >= 2 && is_array(func_get_arg(1))) {
+				$attr = func_get_arg(1);
 			}
+			$tmp = new XMLNode();
+			$tmp->name = $child;
+			$tmp->attributes = $attr;
 		}
+		return $tmp;
 	}
-
 /**
- * Initialize XML object from a given XML string. Returns false on error.
+ * Returns first child node, or null if empty.
  *
- * @param string $in
- * @return boolean Success
+ * @return XMLNode
  */
-	function load($in) {
-		$this->__rawData = null;
-		$this->header = null;
-
-		if (is_string($in)) {
+	function &first() {
+		if(isset($this->children[0])) {
+			return $this->children[0];
+		} else {
+			return null;
+		}
+	}
+/**
+ * Returns last child node, or null if empty.
+ *
+ * @return XMLNode
+ */
+	function &last() {
+		if(count($this->children) > 0) {
+			return $this->children[count($this->children) - 1];
+		} else {
+			return null;
+		}
+	}
+/**
+ * Returns child node with given ID.
+ *
+ * @param string $id Name of childnode
+ * @return XMLNode
+ *
+ */
+	function &child($id) {
+		$null = null;
 
-			if(strstr($in, "<")) {
-				// Input is raw xml data
-				$this->__rawData = $in;
+		if(is_int($id)) {
+			if(isset($this->children[$id])) {
+				return $this->children[$id];
 			} else {
-				// Input is an xml file
-				if(strpos($in, '://') || file_exists($in)) {
-					$this->__rawData = @file_get_contents($in);
-					if ($this->__rawData == null) {
-						$this->error("XML file $in is empty or could not be read (possible permissions error).");
-						return false;
-					}
-				} else {
-					$this->error("XML file $in does not exist");
-					return false;
+				return null;
+			}
+		} elseif(is_string($id)) {
+			for($i = 0; $i < count($this->children); $i++) {
+				if($this->children[$i]->name == $id) {
+					return $this->children[$i];
 				}
 			}
-			return $this->parse();
-
-		} elseif (is_object($in)) {
-		
+			return $null;
+		} else {
+			return $null;
 		}
 	}
 /**
- * Parses and creates XML nodes from the __rawData property.
- *
- * @see load()
+ * Gets a list of childnodes with the given tag name.
  *
+ * @param string $name Tag name of child nodes
+ * @return array An array of XMLNodes with the given tag name
  */
-	function parse() {
-		$this->header = trim(r(a('<'.'?', '?'.'>'), a('', ''), substr(trim($this->__rawData), 0, strpos($this->__rawData, "\n"))));
-
-		xml_parse_into_struct($this->__parser, $this->__rawData, $vals);
-		$xml = new XMLNode();
-
-		$count = count($vals);
-		for ($i = 0; $i < $count; $i++) {
-			$data = $vals[$i];
-			switch($data['type']) {
-				case "open" :
-					$tmpXML = new XMLNode();
-					$tmpXML->name = $data['tag'];
-
-					if(isset($data['value'])) {
-						$tmpXML->value = $data['value'];
-					}
-					if(isset($data['attributes'])) {
-						$tmpXML->attributes = $data['attributes'];
-					}
-
-					$tmpXML->setParent($xml);
-					$ct = count($xml->children);
-					$xml->children[$ct] = $tmpXML;
-					$xml =& $xml->children[$ct];
-				break;
-
-				case "close" :
-					$xml =& $xml->parent();
-				break;
-
-				case "complete" :
-					$tmpXML = new XMLNode();
-					$tmpXML->name = $data['tag'];
-
-					if(isset($data['value'])) {
-						$tmpXML->value = $data['value'];
-					}
-					if(isset($data['attributes'])) {
-						$tmpXML->attributes = $data['attributes'];
-					}
-
-					$tmpXML->__parent =& $xml;
-					$xml->children[] = $tmpXML;
-				break;
-				case 'cdata':
-					if (is_string($xml->value)) {
-						$xml->value = a($xml->value, $data['value']);
-					} else {
-						$xml->value[] = $data['value'];
-					}
-				break;
+	function children($name) {
+		$nodes = array();
+		$count = count($this->children);
+		for($i = 0; $i < $count; $i++) {
+			if($this->children[$i]->name == $name) {
+				$nodes[] =& $this->children[$i];
 			}
 		}
-		$this->children =& $xml->children;
-		return true;
+		return $nodes;
 	}
 /**
- * Returns a string representation of the XML object
+ * Gets a reference to the next child node in the list of this node's parent
  *
- * @param boolean $useHeader Whether to include the XML header with the document (defaults to true)
- * @return string XML data
+ * @return XMLNode A reference to the XMLNode object
  */
-	function compose($useHeader = true) {
-		if (!empty($this->__header)) {
-			$header =  '<'.'?'.$this->__header.' ?'.'>'."\n";
-		} else {
-			$header =  '<'.'?xml version="'.$this->version.'" encoding="'.$this->encoding.'" ?'.'>'."\n";
-		}
-		if (!$this->hasChildren() && !$useHeader) {
-			return null;
-		} elseif (!$this->hasChildren()) {
-			return $header;
-		}
-
-		$data = '';
-		foreach ($this->children as $i => $node) {
-			$data .= $this->children[$i]->__toString();
-		}
-
-		if ($useHeader) {
-			return $header.$data;
+	function &nextSibling() {
+		$count = count($this->__parent->children);
+		for ($i = 0; $i < $count; $i++) {
+			if ($this->__parent->children === $this) {
+				if ($i >= $count - 1 || !isset($this->__parent->children[$i + 1])) {
+					return null;
+				}
+				return $this->__parent->children[$i + 1];
+			}
 		}
-		return $data;
 	}
 /**
- * If DEBUG is on, this method echoes an error message.
+ * Gets a reference to the previous child node in the list of this node's parent
  *
- * @param string $msg Error message
- * @param integer $code Error code
- * @param integer $line Line in file
+ * @return XMLNode A reference to the XMLNode object
  */
-	function error($msg, $code = 0, $line = 0) {
-		if(DEBUG) {
-			echo $msg . " " . $code . " " . $line;
+	function &previousSibling() {
+		$count = count($this->__parent->children);
+		for ($i = 0; $i < $count; $i++) {
+			if ($this->__parent->children === $this) {
+				if ($i == 0 || !isset($this->__parent->children[$i - 1])) {
+					return null;
+				}
+				return $this->__parent->children[$i - 1];
+			}
 		}
 	}
 /**
- * Returns a string with a textual description of the error code, or FALSE if no description was found. 
+ * Returns parent node.
  *
- * @param integer $code
- * @return string Error message
+ * @return XMLNode
  */
-	function getError($code) {
-		$r = @xml_error_string($code);
-		return $r;
+	function &parent() {
+		return $this->__parent;
 	}
-
-// Overridden functions from superclass
-
 /**
- * Enter description here...
+ * Returns true if this structure has child nodes.
  *
- * @return unknown
+ * @return boolean
  */
-	function &next() {
-		return null;
+	function hasChildren() {
+		if(is_array($this->children) && count($this->children) > 0) {
+			return true;
+		}
+		return false;
 	}
 /**
- * Enter description here...
+ * Returns this XML structure as a string.
  *
- * @return null
+ * @return string String representation of the XML structure.
  */
-	function &previous() {
-		return null;
+	function toString() {
+		$d = '';
+		if($this->name != '') {
+			$d .= '<' . $this->name;
+			if(is_array($this->attributes) && count($this->attributes) > 0) {
+				foreach($this->attributes as $key => $val) {
+					$d .= " $key=\"$val\"";
+				}
+			}
+		}
+
+		if(!$this->hasChildren() && empty($this->value)) {
+			if($this->name != '') {
+				$d .= " />\n";
+			}
+		} else {
+			if($this->name != '') {
+				$d .= ">";
+			}
+			if($this->hasChildren()) {
+				if (is_string($this->value) || empty($this->value)) {
+					if (!empty($this->value)) {
+						$d .= $this->value;
+					}
+					$count = count($this->children);
+
+					for($i = 0; $i < $count; $i++) {
+						$d .= $this->children[$i]->toString();
+					}
+				} elseif (is_array($this->value)) {
+					$count = count($this->value);
+					for($i = 0; $i < $count; $i++) {
+						$d .= $this->value[$i];
+						if (isset($this->children[$i])) {
+							$d .= $this->children[$i]->toString();
+						}
+					}
+					$count = count($this->children);
+					if ($i < $count) {
+						for ($i = $i; $i < $count; $i++) {
+							$d .= $this->children[$i]->toString();
+						}
+					}
+				}
+			}
+
+			if (is_string($this->value)) {
+				$d .= $this->value;
+			}
+
+			if($this->name != '' && ($this->hasChildren() || !empty($this->value))) {
+				$d .= "</" . $this->name . ">\n";
+			}
+		}
+		return $d;
 	}
 /**
- * Enter description here...
+ * Returns data from toString when this object is converted to a string.
  *
- * @return null
+ * @return string String representation of this structure.
  */
-	function &parent() {
-		return null;
-	}
-
-	function toString() {
-		return $this->compose();
+	function __toString() {
+		return $this->toString();
 	}
-
-	function __destruct() {
-		if (is_resource($this->__parser)) {
-			xml_parser_free($this->__parser);
+/**
+ * Debug method. Deletes the parent. Also deletes this node's children,
+ * if given the $recursive parameter.
+ *
+ * @param boolean $recursive
+ */
+	function __killParent($recursive = true) {
+		unset($this->__parent);
+		if($recursive && $this->hasChildren()) {
+			for($i = 0; $i < count($this->children); $i++) {
+				$this->children[$i]->__killParent(true);
+			}
 		}
 	}
 }
 
 /**
- * XML node.
+ * XML handling.
  *
- * Single XML node in an XML tree.
+ * Operations on XML data.
  *
  * @package    cake
  * @subpackage cake.cake.libs
  * @since      CakePHP v .0.10.3.1400
  */
-class XMLNode extends Object {
+class XML extends XMLNode {
+
 /**
- * Name of node
+ * Resource handle to XML parser.
  *
- * @var string
+ * @var resource
  */
-	var $name = null;
+	var $__parser;
 /**
- * Value of node
+ * File handle to XML indata file.
  *
- * @var string
+ * @var resource
  */
-	var $value;
+	var $__file;
 /**
- * Attributes on this node
+ * Raw XML string data (for loading purposes)
  *
- * @var array
+ * @var string
  */
-	var $attributes = array();
+	var $__rawData = null;
+
 /**
- * This node's children
+ * XML document header
  *
- * @var array
+ * @var string
  */
-	var $children = array();
+	var $__header = null;
+
 /**
- * Reference to parent node.
+ * XML document version
  *
- * @var XMLNode
+ * @var string
  */
-	var $__parent = null;
+	var $version = '1.0';
+
 /**
- * Constructor.
+ * XML document encoding
  *
- * @param string $name Node name
- * @param array  $attributes Node attributes
- * @param mixed  $value Node contents (text)
+ * @var string
  */
-	function __construct($name = null, $attributes = array(), $value = null, $children = array()) {
-		$this->name = $name;
-		$this->attributes = $attributes;
-		$this->value = $value;
+	var $encoding = 'UTF-8';
 
-		$c = count($children);
-		for ($i = 0; $i < $c; $i++) {
-			if (is_a($children[$i], 'XMLNode') || is_a($children[$i], 'xmlnode')) {
-				$this->append($children[$i]);
-			} elseif (is_array($children[$i])) {
-				$cName = '';
-				$cAttr = $cChildren = array();
-				list($cName, $cAttr, $cChildren) = $children[$i];
-				$node = new XMLNode($name, $cAttr, $cChildren);
-				$this->append($node);
-				unset($node);
-			} else {
-				$child = $children[$i];
-				$this->append($child);
-				unset($child);
-			}
-		}
-	}
 /**
- * Gets the XML element properties from an object
+ * Constructor.  Sets up the XML parser with options, gives it this object as
+ * its XML object, and sets some variables.
  *
- * @param object $object
- * @return array
+ * @param string $input
  */
-	function __objectToNode($object) {
+	function __construct($input = null, $options = array()) {
+		parent::__construct('root');
+		$this->__parser = xml_parser_create_ns();
 
-		if (is_array($object)) {
-			$objects = array();
-			foreach ($object as $obj) {
-				$objects[] = $this->__objectToNode($obj);
-			}
-			return $objects;
-		}
+		xml_set_object($this->__parser, $this);
+		xml_parser_set_option($this->__parser, XML_OPTION_CASE_FOLDING, 0);
+		xml_parser_set_option($this->__parser, XML_OPTION_SKIP_WHITE, 1);
 
-		if (isset($object->__identity__) && !empty($object->__identity__)) {
-			$name = $object->__identity__;
-		} elseif (isset($object->name) && $object->name != null) {
-			$name = $object->name;
-		} else {
-			$name = get_class($object);
-		}
-		if ($name != low($name)) {
-			$name = Inflector::underscore($name);
-		}
+		$this->children = array();
 
-		if (is_object($object)) {
-			$attributes = get_object_vars($object);
-		} elseif (is_array($object)) {
-			$attributes = $object[$name];
-			if (is_object($attributes)) {
-				$attributes = get_object_vars($attributes);
+		if($input != null) {
+			$vars = null;
+			if (is_string($input)) {
+				$this->load($input);
+			} elseif (is_array($input)) {
+				$vars = $this->__objectToNode(Set::map($input));
+			} elseif (is_object($input)) {
+				$vars = $this->__objectToNode($input);
 			}
-		}
 
-		$children = array();
-		$attr = $attributes;
+			if ($vars != null) {
+				$this->children = $vars;
+			}
 
-		foreach ($attr as $key => $val) {
-			if (is_array($val)) {
-				foreach ($val as $i => $obj2) {
-					$children[] = $this->__objectToNode($obj2);
-					unset($attributes[$key]);
-				}
-			} elseif (is_object($val)) {
-				$children[] = $this->__objectToNode($val);
-				unset($attributes[$key]);
+			if (!is_array($this->children)) {
+				$this->children = array($this->children);
 			}
 		}
-		unset($attributes['__identity__']);
 
-		$node = new XMLNode($name, $attributes, null, $children);
-		return $node;
+		foreach ($options as $key => $val) {
+			switch ($key) {
+				case 'version':
+					$this->version = $val;
+				break;
+				case 'encoding':
+					$this->encoding = $val;
+				break;
+			}
+		}
 	}
+
 /**
- * Sets the parent node of this XMLNode
+ * Initialize XML object from a given XML string. Returns false on error.
  *
- * @return XMLNode
+ * @param string $in
+ * @return boolean Success
  */
-	function setParent(&$parent) {
-		$this->__parent =& $parent;
+	function load($in) {
+		$this->__rawData = null;
+		$this->header = null;
+
+		if (is_string($in)) {
+
+			if(strstr($in, "<")) {
+				// Input is raw xml data
+				$this->__rawData = $in;
+			} else {
+				// Input is an xml file
+				if(strpos($in, '://') || file_exists($in)) {
+					$this->__rawData = @file_get_contents($in);
+					if ($this->__rawData == null) {
+						$this->error("XML file $in is empty or could not be read (possible permissions error).");
+						return false;
+					}
+				} else {
+					$this->error("XML file $in does not exist");
+					return false;
+				}
+			}
+			return $this->parse();
+
+		} elseif (is_object($in)) {
+		
+		}
 	}
 /**
- * Returns a copy of self.
+ * Parses and creates XML nodes from the __rawData property.
  *
- * @return XMLNode
- */
-	function cloneNode() {
-		return $this;
-	}
-/**
- * Append given node as a child.
+ * @see load()
  *
- * @param XMLNode $child
  */
-	function &append(&$child) {
-		if (is_object($child)) {
-			$this->children[] =& $child;
-		} elseif (is_string($child)) {
-			$attr = array();
-			if (func_num_args() >= 2 && is_array(func_get_arg(1))) {
-				$attr = func_get_arg(1);
+	function parse() {
+		$this->header = trim(r(a('<'.'?', '?'.'>'), a('', ''), substr(trim($this->__rawData), 0, strpos($this->__rawData, "\n"))));
+
+		xml_parse_into_struct($this->__parser, $this->__rawData, $vals);
+		$xml = new XMLNode();
+
+		$count = count($vals);
+		for ($i = 0; $i < $count; $i++) {
+			$data = $vals[$i];
+			switch($data['type']) {
+				case "open" :
+					$tmpXML = new XMLNode();
+					$tmpXML->name = $data['tag'];
+
+					if(isset($data['value'])) {
+						$tmpXML->value = $data['value'];
+					}
+					if(isset($data['attributes'])) {
+						$tmpXML->attributes = $data['attributes'];
+					}
+
+					$tmpXML->setParent($xml);
+					$ct = count($xml->children);
+					$xml->children[$ct] = $tmpXML;
+					$xml =& $xml->children[$ct];
+				break;
+
+				case "close" :
+					$xml =& $xml->parent();
+				break;
+
+				case "complete" :
+					$tmpXML = new XMLNode();
+					$tmpXML->name = $data['tag'];
+
+					if(isset($data['value'])) {
+						$tmpXML->value = $data['value'];
+					}
+					if(isset($data['attributes'])) {
+						$tmpXML->attributes = $data['attributes'];
+					}
+
+					$tmpXML->__parent =& $xml;
+					$xml->children[] = $tmpXML;
+				break;
+				case 'cdata':
+					if (is_string($xml->value)) {
+						$xml->value = a($xml->value, $data['value']);
+					} else {
+						$xml->value[] = $data['value'];
+					}
+				break;
 			}
-			$tmp = new XMLNode();
-			$tmp->name = $child;
-			$tmp->attributes = $attr;
 		}
-		return $tmp;
+		$this->children =& $xml->children;
+		return true;
 	}
 /**
- * Returns first child node, or null if empty.
+ * Returns a string representation of the XML object
  *
- * @return XMLNode
+ * @param boolean $useHeader Whether to include the XML header with the document (defaults to true)
+ * @return string XML data
  */
-	function &first() {
-		if(isset($this->children[0])) {
-			return $this->children[0];
+	function compose($useHeader = true) {
+		if (!empty($this->__header)) {
+			$header =  '<'.'?'.$this->__header.' ?'.'>'."\n";
 		} else {
-			return null;
+			$header =  '<'.'?xml version="'.$this->version.'" encoding="'.$this->encoding.'" ?'.'>'."\n";
 		}
-	}
-/**
- * Returns last child node, or null if empty.
- *
- * @return XMLNode
- */
-	function &last() {
-		if(count($this->children) > 0) {
-			return $this->children[count($this->children) - 1];
-		} else {
+		if (!$this->hasChildren() && !$useHeader) {
 			return null;
+		} elseif (!$this->hasChildren()) {
+			return $header;
 		}
-	}
-/**
- * Returns child node with given ID.
- *
- * @param string $id Name of childnode
- * @return XMLNode
- *
- */
-	function &child($id) {
-		$null = null;
 
-		if(is_int($id)) {
-			if(isset($this->children[$id])) {
-				return $this->children[$id];
-			} else {
-				return null;
-			}
-		} elseif(is_string($id)) {
-			for($i = 0; $i < count($this->children); $i++) {
-				if($this->children[$i]->name == $id) {
-					return $this->children[$i];
-				}
-			}
-			return $null;
-		} else {
-			return $null;
+		$data = '';
+		foreach ($this->children as $i => $node) {
+			$data .= $this->children[$i]->__toString();
 		}
-	}
-/**
- * Gets a list of childnodes with the given tag name.
- *
- * @param string $name Tag name of child nodes
- * @return array An array of XMLNodes with the given tag name
- */
-	function children($name) {
-		$nodes = array();
-		$count = count($this->children);
-		for($i = 0; $i < $count; $i++) {
-			if($this->children[$i]->name == $name) {
-				$nodes[] =& $this->children[$i];
-			}
+
+		if ($useHeader) {
+			return $header.$data;
 		}
-		return $nodes;
+		return $data;
 	}
 /**
- * Gets a reference to the next child node in the list of this node's parent
+ * If DEBUG is on, this method echoes an error message.
  *
- * @return XMLNode A reference to the XMLNode object
+ * @param string $msg Error message
+ * @param integer $code Error code
+ * @param integer $line Line in file
  */
-	function &nextSibling() {
-		$count = count($this->__parent->children);
-		for ($i = 0; $i < $count; $i++) {
-			if ($this->__parent->children === $this) {
-				if ($i >= $count - 1 || !isset($this->__parent->children[$i + 1])) {
-					return null;
-				}
-				return $this->__parent->children[$i + 1];
-			}
+	function error($msg, $code = 0, $line = 0) {
+		if(DEBUG) {
+			echo $msg . " " . $code . " " . $line;
 		}
 	}
 /**
- * Gets a reference to the previous child node in the list of this node's parent
+ * Returns a string with a textual description of the error code, or FALSE if no description was found. 
  *
- * @return XMLNode A reference to the XMLNode object
+ * @param integer $code
+ * @return string Error message
  */
-	function &previousSibling() {
-		$count = count($this->__parent->children);
-		for ($i = 0; $i < $count; $i++) {
-			if ($this->__parent->children === $this) {
-				if ($i == 0 || !isset($this->__parent->children[$i - 1])) {
-					return null;
-				}
-				return $this->__parent->children[$i - 1];
-			}
-		}
+	function getError($code) {
+		$r = @xml_error_string($code);
+		return $r;
 	}
+
+// Overridden functions from superclass
+
 /**
- * Returns parent node.
+ * Enter description here...
  *
- * @return XMLNode
+ * @return unknown
  */
-	function &parent() {
-		return $this->__parent;
+	function &next() {
+		return null;
 	}
 /**
- * Returns true if this structure has child nodes.
+ * Enter description here...
  *
- * @return boolean
+ * @return null
  */
-	function hasChildren() {
-		if(is_array($this->children) && count($this->children) > 0) {
-			return true;
-		}
-		return false;
+	function &previous() {
+		return null;
 	}
 /**
- * Returns this XML structure as a string.
+ * Enter description here...
  *
- * @return string String representation of the XML structure.
+ * @return null
  */
-	function toString() {
-		$d = '';
-		if($this->name != '') {
-			$d .= '<' . $this->name;
-			if(is_array($this->attributes) && count($this->attributes) > 0) {
-				foreach($this->attributes as $key => $val) {
-					$d .= " $key=\"$val\"";
-				}
-			}
-		}
-
-		if(!$this->hasChildren() && empty($this->value)) {
-			if($this->name != '') {
-				$d .= " />\n";
-			}
-		} else {
-			if($this->name != '') {
-				$d .= ">";
-			}
-			if($this->hasChildren()) {
-				if (is_string($this->value) || empty($this->value)) {
-					if (!empty($this->value)) {
-						$d .= $this->value;
-					}
-					$count = count($this->children);
-
-					for($i = 0; $i < $count; $i++) {
-						$d .= $this->children[$i]->toString();
-					}
-				} elseif (is_array($this->value)) {
-					$count = count($this->value);
-					for($i = 0; $i < $count; $i++) {
-						$d .= $this->value[$i];
-						if (isset($this->children[$i])) {
-							$d .= $this->children[$i]->toString();
-						}
-					}
-					$count = count($this->children);
-					if ($i < $count) {
-						for ($i = $i; $i < $count; $i++) {
-							$d .= $this->children[$i]->toString();
-						}
-					}
-				}
-			}
-
-			if (is_string($this->value)) {
-				$d .= $this->value;
-			}
-
-			if($this->name != '' && ($this->hasChildren() || !empty($this->value))) {
-				$d .= "</" . $this->name . ">\n";
-			}
-		}
-		return $d;
+	function &parent() {
+		return null;
 	}
-/**
- * Returns data from toString when this object is converted to a string.
- *
- * @return string String representation of this structure.
- */
-	function __toString() {
-		return $this->toString();
+
+	function toString() {
+		return $this->compose();
 	}
-/**
- * Debug method. Deletes the parent. Also deletes this node's children,
- * if given the $recursive parameter.
- *
- * @param boolean $recursive
- */
-	function __killParent($recursive = true) {
-		unset($this->__parent);
-		if($recursive && $this->hasChildren()) {
-			for($i = 0; $i < count($this->children); $i++) {
-				$this->children[$i]->__killParent(true);
-			}
+
+	function __destruct() {
+		if (is_resource($this->__parser)) {
+			xml_parser_free($this->__parser);
 		}
 	}
 }