00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 lt_include(PLOG_CLASS_PATH."class/xml/parser/Parser.php");
00026 lt_include(PLOG_CLASS_PATH."class/xml/tree/Node.php");
00027
00051 class XML_Tree extends XML_Parser
00052 {
00058 var $file = NULL;
00059
00065 var $filename = '';
00066
00072 var $namespace = array();
00073
00079 var $root = NULL;
00080
00086 var $version = '1.0';
00087
00094 var $use_cdata_sections = false;
00095
00102 function XML_Tree($filename = '', $version = '1.0')
00103 {
00104 $this->filename = $filename;
00105 $this->version = $version;
00106 }
00107
00114 function useCdataSections()
00115 {
00116 $this->use_cdata_sections = true;
00117 }
00118
00126 function &getRoot()
00127 {
00128 if (!is_null($this->root)) {
00129 return $this->root;
00130 }
00131 return $this->raiseError("No root");
00132 }
00133
00142 function &addRoot($name, $content = '', $attributes = array(), $lineno = null)
00143 {
00144 $this->root = new XML_Tree_Node($name, $content, $attributes, $lineno);
00145 return $this->root;
00146 }
00147
00167 function &insertChild($path, $pos, $child, $content = '', $attributes = array())
00168 {
00169 $parent =& $this->getNodeAt($path);
00170 if (!$parent) {
00171 return $parent;
00172 }
00173
00174 $x =& $parent->insertChild(null, $pos, $child, $content, $attributes);
00175
00176 if (!$this->isError($x)) {
00177
00178 $count = count($path);
00179 foreach ($this->namespace as $key => $val) {
00180 if ((array_slice($val,0,$count)==$path) && ($val[$count]>=$pos)) {
00181 $this->namespace[$key][$count]++;
00182 }
00183 }
00184 }
00185 return $x;
00186 }
00187
00201 function &removeChild($path, $pos)
00202 {
00203 $parent =& $this->getNodeAt($path);
00204 if ($this->isError($parent)) {
00205 return $parent;
00206 }
00207
00208 $x =& $parent->removeChild($pos);
00209
00210 if (!$this->isError($x)) {
00211
00212 $count=count($path);
00213 foreach($this->namespace as $key => $val) {
00214 if (array_slice($val,0,$count)==$path) {
00215 if ($val[$count]==$pos) {
00216 unset($this->namespace[$key]); break;
00217 }
00218 if ($val[$count]>$pos) {
00219 $this->namespace[$key][$count]--;
00220 }
00221 }
00222 }
00223 }
00224
00225 return $x;
00226 }
00227
00234 function &getTreeFromFile ()
00235 {
00236 $this->folding = false;
00237 $this->XML_Parser(null, 'event');
00238 $err = $this->setInputFile($this->filename);
00239 if ($this->isError($err)) {
00240 return $err;
00241 }
00242 $this->cdata = null;
00243 $err = $this->parse();
00244 if ($this->isError($err)) {
00245 return $err;
00246 }
00247 return $this->root;
00248 }
00249
00256 function &getTreeFromString($str)
00257 {
00258 $this->i = null;
00259 $this->folding = false;
00260 $this->XML_Parser(null, 'event');
00261 $this->cdata = null;
00262 $err = $this->parseString($str);
00263 if ($this->isError($err)) {
00264 return $err;
00265 }
00266 return $this->root;
00267 }
00268
00279 function startHandler($xp, $elem, &$attribs)
00280 {
00281 $lineno = xml_get_current_line_number($xp);
00282
00283
00284 if (!isset($this->i)) {
00285 $this->obj1 =& $this->addRoot($elem, null, $attribs, $lineno);
00286 $this->i = 2;
00287 } else {
00288
00289 if (!empty($this->cdata)) {
00290 $parent_id = 'obj' . ($this->i - 1);
00291 $parent =& $this->$parent_id;
00292
00293 }
00294 $obj_id = 'obj' . $this->i++;
00295 $this->$obj_id = &new XML_Tree_Node($elem, null, $attribs, $lineno);
00296 }
00297 $this->cdata = null;
00298 return null;
00299 }
00300
00310 function endHandler($xp, $elem)
00311 {
00312 $this->i--;
00313 if ($this->i > 1) {
00314 $obj_id = 'obj' . $this->i;
00315
00316 $node =& $this->$obj_id;
00317
00318 if (count($node->children) > 0) {
00319 if (trim($this->cdata) != '') {
00320 $node->children[] = &new XML_Tree_Node(null, $this->cdata);
00321 }
00322 } else {
00323 $node->setContent($this->cdata);
00324 }
00325 $parent_id = 'obj' . ($this->i - 1);
00326 $parent =& $this->$parent_id;
00327
00328 $parent->children[] = $node;
00329 } else {
00330 $node =& $this->obj1;
00331 if (count($node->children) > 0) {
00332 if (trim($this->cdata)) {
00333 $node->children[] = &new XML_Tree_Node(null, $this->cdata);
00334 }
00335 } else {
00336 $node->setContent($this->cdata);
00337 }
00338 }
00339 $this->cdata = null;
00340 return null;
00341 }
00342
00352 function cdataHandler($xp, $data)
00353 {
00354 $this->cdata .= $data;
00355 }
00356
00363 function cloneTree()
00364 {
00365 $clone = new XML_Tree($this->filename, $this->version);
00366 if (!is_null($this->root)) {
00367 $clone->root = $this->root->cloneTree();
00368 }
00369
00370
00371 $temp = get_object_vars($this);
00372 foreach($temp as $varname => $value) {
00373 if (!in_array($varname,array('filename','version','root'))) {
00374 $clone->$varname=$value;
00375 }
00376 }
00377 return $clone;
00378 }
00379
00389 function dump($xmlHeader = false)
00390 {
00391 if ($xmlHeader) {
00392 header('Content-type: text/xml');
00393 }
00394 echo $this->get($this->use_cdata_sections);
00395 }
00396
00403 function &get()
00404 {
00405 $out = '<?xml version="' . $this->version . "\"?>\n";
00406
00407 if (!is_null($this->root))
00408 {
00409 if(!is_object($this->root) || (strtolower(get_class($this->root)) != 'xml_tree_node'))
00410 return $this->raiseError("Bad XML root node");
00411 $out .= $this->root->get($this->use_cdata_sections);
00412 }
00413 return $out;
00414 }
00415
00424 function &getName($name) {
00425 return $this->root->getElement($this->namespace[$name]);
00426 }
00427
00432 function getNodeNamespace(&$node) {
00433 $name_parts = explode(':',$node->name);
00434 if (sizeof($name_parts) > 1) {
00435 $namespace = $name_parts[0];
00436 } else {
00437 $namespace = '';
00438 }
00439
00440 if (isset($node->namespace[$namespace])) {
00441 return $node->namespace[$namespace];
00442 } elseif (isset($this->root->namespace[$namespace])) {
00443 return $this->root->namespace[$namespace];
00444 } else {
00445 return '';
00446 }
00447 }
00448
00461 function &getNodeAt($path)
00462 {
00463 if (is_null($this->root)){
00464
00465 return false;
00466 }
00467 if (is_string($path))
00468 $path = explode("/", $path);
00469 if (sizeof($path) == 0) {
00470
00471 return false;
00472 }
00473 $path1 = $path;
00474 $rootName = array_shift($path1);
00475 if ($this->root->name != $rootName) {
00476
00477 return false;
00478 }
00479 $x =& $this->root->getNodeAt($path1);
00480
00481 if ( $x ) {
00482 return $x;
00483 }
00484
00485
00486 $x = false;
00487 return $x;
00488 }
00489
00500 function &getElementsByTagName($tagName)
00501 {
00502 if (empty($tagName)) {
00503 return $this->raiseError('Empty tag name');
00504 }
00505 $result = array();
00506 foreach ($this->root->children as $child) {
00507 if ($child->name == $tagName) {
00508 $result[] = $child;
00509 }
00510 }
00511 return $result;
00512 }
00513
00526 function &getElementsByTagNameFromNode($tagName, &$node)
00527 {
00528 if (empty($tagName)) {
00529 return $this->raiseError('Empty tag name');
00530 }
00531 $result = array();
00532 foreach ($node->children as $child) {
00533 if ($child->name == $tagName) {
00534 $result[] = $child;
00535 }
00536 }
00537 return $result;
00538 }
00539
00540
00549 function isValidName($name, $type) {
00550 if (trim($name) == '') {
00551 return true;
00552 }
00553
00554
00555 if (!preg_match("/[[:alpha:]_]/", $name{0})) {
00556
00557 return false;
00558 }
00559
00560 if (!preg_match("/^([a-zA-Z_]([a-zA-Z0-9_\-\.]*)?:)?[a-zA-Z_]([a-zA-Z0-9_\-\.]+)?$/", $name)) {
00561
00562 return false;
00563 }
00564
00565 return true;
00566 }
00567 }
00568 ?>