| // | Sebastian Bergmann | // | Tomas V.V.Cox (tree mapping from xml file)| // +----------------------------------------------------------------------+ // // $Id$ // require_once 'XML/Parser.php'; require_once 'XML/Tree/Node.php'; /** * PEAR::XML_Tree * * Purpose * * Allows for the building of XML data structures * using a tree representation, without the need * for an extension like DOMXML. * * Example * * $tree = new XML_Tree; * $root =& $tree->addRoot('root'); * $foo =& $root->addChild('foo'); * * header('Content-Type: text/xml'); * $tree->dump(); * * @author Bernd Römer * @package XML * @version $Version$ - 1.0 */ class XML_Tree extends XML_Parser { /** * File Handle * * @var ressource */ var $file = NULL; /** * Filename * * @var string */ var $filename = ''; /** * Namespace * * @var array */ var $namespace = array(); /** * Root * * @var object XML_Tree_Node */ var $root = NULL; /** * XML Version * * @var string */ var $version = '1.0'; /** * Constructor * * @param string Filename * @param string XML Version */ function XML_Tree($filename = '', $version = '1.0') { $this->filename = $filename; $this->version = $version; } /** * Add root node. * * @param string $name name of root element * @return object XML_Tree_Node reference to root node * * @access public */ function &addRoot($name, $content = '', $attributes = array()) { $this->root = new XML_Tree_Node($name, $content, $attributes); return $this->root; } /** * @deprecated */ function &add_root($name, $content = '', $attributes = array()) { return $this->addRoot($name, $content, $attributes); } /** * inserts a child/tree (child) into tree ($path,$pos) and * maintains namespace integrity * * @param array $path path to parent of child to remove * @param integer $pos position of child to be inserted in its parents children-list * @param mixed $child child-node (by XML_Tree,XML_Node or Name) * @param string $content content (text) for new node * @param array $attributes attribute-hash for new node * * @return object XML_Tree_Node inserted child (node) * @access public */ function &insertChild($path,$pos,$child, $content = '', $attributes = array()) { // update namespace to maintain namespace integrity $count=count($path); foreach($this->namespace as $key => $val) { if ((array_slice($val,0,$count)==$path) && ($val[$count]>=$pos)) $this->namespace[$key][$count]++; } $parent=&$this->get_node_by_path($path); return($parent->insert_child($pos,$child,$content,$attributes)); } /** * @deprecated */ function &insert_child($path,$pos,$child, $content = '', $attributes = array()) { return $this->insertChild($path, $child, $content, $attributes); } /* * removes a child ($path,$pos) from tree ($path,$pos) and * maintains namespace integrity * * @param array $path path to parent of child to remove * @param integer $pos position of child in parents children-list * * @return object XML_Tree_Node parent whichs child was removed * @access public */ function &removeChild($path,$pos) { // update namespace to maintain namespace integrity $count=count($path); foreach($this->namespace as $key => $val) { if (array_slice($val,0,$count)==$path) { if ($val[$count]==$pos) { unset($this->namespace[$key]); break; } if ($val[$count]>$pos) $this->namespace[$key][$count]--; } } $parent=&$this->get_node_by_path($path); return($parent->remove_child($pos)); } /** * @deprecated */ function &remove_child($path, $pos) { return $this->removeChild($path, $pos); } /* * Maps a xml file to a objects tree * * @return mixed The objects tree (XML_tree or an Pear error) * @access public */ function &getTreeFromFile () { $this->folding = false; $this->XML_Parser(null, 'event'); $err = $this->setInputFile($this->filename); if (PEAR::isError($err)) { return $err; } $this->cdata = null; $err = $this->parse(); if (PEAR::isError($err)) { return $err; } return $this->root; } function getTreeFromString($str) { $this->folding = false; $this->XML_Parser(null, 'event'); $this->cdata = null; $err = $this->parseString($str); if (PEAR::isError($err)) { return $err; } return $this->root; } /** * Handler for the xml-data * * @param mixed $xp ignored * @param string $elem name of the element * @param array $attribs attributes for the generated node * * @access private */ function startHandler($xp, $elem, &$attribs) { // root elem if (!isset($this->i)) { $this->obj1 =& $this->add_root($elem, null, $attribs); $this->i = 2; } else { // mixed contents if (!empty($this->cdata)) { $parent_id = 'obj' . ($this->i - 1); $parent =& $this->$parent_id; $parent->children[] = &new XML_Tree_Node(null, $this->cdata); } $obj_id = 'obj' . $this->i++; $this->$obj_id = &new XML_Tree_Node($elem, null, $attribs); } $this->cdata = null; return null; } /** * Handler for the xml-data * * @param mixed $xp ignored * @param string $elem name of the element * * @access private */ function endHandler($xp, $elem) { $this->i--; if ($this->i > 1) { $obj_id = 'obj' . $this->i; // recover the node created in StartHandler $node =& $this->$obj_id; // mixed contents if (count($node->children) > 0) { if (trim($this->cdata)) { $node->children[] = &new XML_Tree_Node(null, $this->cdata); } } else { $node->set_content($this->cdata); } $parent_id = 'obj' . ($this->i - 1); $parent =& $this->$parent_id; // attach the node to its parent node children array $parent->children[] = $node; } $this->cdata = null; return null; } /* * The xml character data handler * * @param mixed $xp ignored * @param string $data PCDATA between tags * * @access private */ function cdataHandler($xp, $data) { if (trim($data)) { $this->cdata .= $data; } } /** * Get a copy of this tree. * * @return object XML_Tree * @access public */ function clone() { $clone=new XML_Tree($this->filename,$this->version); $clone->root=$this->root->clone(); // clone all other vars $temp=get_object_vars($this); foreach($temp as $varname => $value) if (!in_array($varname,array('filename','version','root'))) $clone->$varname=$value; return($clone); } /** * Print text representation of XML tree. * * @access public */ function dump() { echo $this->get(); } /** * Get text representation of XML tree. * * @return string XML * @access public */ function &get() { $out = 'version . "\"?>\n"; $out .= $this->root->get(); return $out; } /** * Get current namespace. * * @param string $name namespace * @return string * * @access public */ function &getName($name) { return $this->root->get_element($this->namespace[$name]); } /** * @deprecated */ function &get_name($name) { return $this->getName($name); } /** * Register a namespace. * * @param string $name namespace * @param string $path path * * @access public */ function registerName($name, $path) { $this->namespace[$name] = $path; } /** * @deprecated */ function register_name($name, $path) { return $this->registerName($name, $path); } } ?>