Back to index

awl  0.53
XMLElement.php
Go to the documentation of this file.
00001 <?php
00012 require_once('AWLUtilities.php');
00013 
00020 class XMLElement {
00021   protected $tagname;
00022   protected $xmlns;
00023   protected $attributes;
00024   protected $content;
00025   protected $_parent;
00026 
00035   function __construct( $tagname, $content=false, $attributes=false, $xmlns=null ) {
00036     $this->tagname=$tagname;
00037     if ( gettype($content) == "object" ) {
00038       // Subtree to be parented here
00039       $this->content = array(&$content);
00040     }
00041     else {
00042       // Array or text
00043       $this->content = $content;
00044     }
00045     $this->attributes = $attributes;
00046     if ( isset($xmlns) ) {
00047       $this->xmlns = $xmlns;
00048     }
00049     else {
00050       if ( preg_match( '{^(.*):([^:]*)$}', $tagname, $matches) ) {
00051         $prefix = $matches[1];
00052         $tag = $matches[2];
00053         if ( isset($this->attributes['xmlns:'.$prefix]) ) {
00054           $this->xmlns = $this->attributes['xmlns:'.$prefix];
00055         }
00056       }
00057       else if ( isset($this->attributes['xmlns']) ) {
00058         $this->xmlns = $this->attributes['xmlns'];
00059       }
00060     }
00061   }
00062 
00063 
00068   function CountElements( ) {
00069     if ( $this->content === false ) return 0;
00070     if ( is_array($this->content) ) return count($this->content);
00071     if ( $this->content == '' ) return 0;
00072     return 1;
00073   }
00074 
00081   function SetAttribute($k,$v) {
00082     if ( gettype($this->attributes) != "array" ) $this->attributes = array();
00083     $this->attributes[$k] = $v;
00084     if ( strtolower($k) == 'xmlns' ) {
00085       $this->xmlns = $v;
00086     }
00087   }
00088 
00094   function SetContent($v) {
00095     $this->content = $v;
00096   }
00097 
00103   function GetTag() {
00104     return $this->tagname;
00105   }
00106 
00112   function GetNSTag() {
00113     return (empty($this->xmlns) ? '' : $this->xmlns . ':') . $this->tagname;
00114   }
00115 
00121   function GetAttribute( $attr ) {
00122     if ( $attr == 'xmlns' ) return $this->xmlns;
00123     if ( isset($this->attributes[$attr]) ) return $this->attributes[$attr];
00124     return null;
00125   }
00126 
00132   function GetAttributes() {
00133     return $this->attributes;
00134   }
00135 
00141   function GetContent() {
00142     return $this->content;
00143   }
00144 
00151   function GetElements( $tag=null, $recursive=false ) {
00152     $elements = array();
00153     if ( gettype($this->content) == "array" ) {
00154       foreach( $this->content AS $k => $v ) {
00155         if ( empty($tag) || $v->GetNSTag() == $tag ) {
00156           $elements[] = $v;
00157         }
00158         if ( $recursive ) {
00159           $elements = $elements + $v->GetElements($tag,true);
00160         }
00161       }
00162     }
00163     else if ( empty($tag) || (isset($v->content->tagname) && $v->content->GetNSTag() == $tag) ) {
00164       $elements[] = $this->content;
00165     }
00166     return $elements;
00167   }
00168 
00169 
00175   function GetPath( $path ) {
00176     $elements = array();
00177     // printf( "Querying within '%s' for path '%s'\n", $this->tagname, $path );
00178     if ( !preg_match( '#(/)?([^/]+)(/?.*)$#', $path, $matches ) ) return $elements;
00179     // printf( "Matches: %s -- %s -- %s\n", $matches[1], $matches[2], $matches[3] );
00180     if ( $matches[2] == '*' || $matches[2] == $this->GetNSTag()) {
00181       if ( $matches[3] == '' ) {
00185         $elements[] = $this;
00186       }
00187       else if ( gettype($this->content) == "array" ) {
00191         foreach( $this->content AS $k => $v ) {
00192           $elements = array_merge( $elements, $v->GetPath($matches[3]) );
00193         }
00194       }
00195     }
00196 
00197     if ( $matches[1] != '/' && gettype($this->content) == "array" ) {
00201       foreach( $this->content AS $k => $v ) {
00202         $elements = array_merge( $elements, $v->GetPath($path) );
00203       }
00204     }
00205     // printf( "Found %d within '%s' for path '%s'\n", count($elements), $this->tagname, $path );
00206     return $elements;
00207   }
00208 
00209 
00215   function AddSubTag(&$v) {
00216     if ( gettype($this->content) != "array" ) $this->content = array();
00217     $this->content[] =& $v;
00218     return count($this->content);
00219   }
00220 
00230   function &NewElement( $tagname, $content=false, $attributes=false, $xmlns=null ) {
00231     if ( gettype($this->content) != "array" ) $this->content = array();
00232     $element = new XMLElement($tagname,$content,$attributes,$xmlns);
00233     $this->content[] =& $element;
00234     return $element;
00235   }
00236 
00237 
00243   function RenderContent($indent=0, $nslist=null, $force_xmlns=false ) {
00244     $r = "";
00245     if ( is_array($this->content) ) {
00249       $r .= "\n";
00250       foreach( $this->content AS $k => $v ) {
00251         if ( is_object($v) ) {
00252           $r .= $v->Render($indent+1, "", $nslist, $force_xmlns);
00253         }
00254       }
00255       $r .= substr("                        ",0,$indent);
00256     }
00257     else {
00262       $r .= htmlspecialchars($this->content, ENT_NOQUOTES );
00263     }
00264     return $r;
00265   }
00266 
00267 
00273   function Render($indent=0, $xmldef="", $nslist=null, $force_xmlns=false) {
00274     $r = ( $xmldef == "" ? "" : $xmldef."\n");
00275 
00276     $attr = "";
00277     $tagname = $this->tagname;
00278     $xmlns_done = false;
00279     if ( gettype($this->attributes) == "array" ) {
00283       foreach( $this->attributes AS $k => $v ) {
00284         if ( preg_match('#^xmlns(:?(.+))?$#', $k, $matches ) ) {
00285 //          if ( $force_xmlns ) printf( "1: %s: %s\n", $this->tagname, $this->xmlns );
00286           if ( !isset($nslist) ) $nslist = array();
00287           $prefix = (isset($matches[2]) ? $matches[2] : '');
00288           if ( isset($nslist[$v]) && $nslist[$v] == $prefix ) continue; // No need to include in list as it's in a wrapping element
00289           $nslist[$v] = $prefix;
00290           if ( !isset($this->xmlns) ) $this->xmlns = $v;
00291           $xmlns_done = true;
00292         }
00293         $attr .= sprintf( ' %s="%s"', $k, htmlspecialchars($v) );
00294       }
00295     }
00296     if ( isset($this->xmlns) && isset($nslist[$this->xmlns]) && $nslist[$this->xmlns] != '' ) {
00297 //      if ( $force_xmlns ) printf( "2: %s: %s\n", $this->tagname, $this->xmlns );
00298       $tagname = $nslist[$this->xmlns] . ':' . $tagname;
00299       if ( $force_xmlns ) $attr .= sprintf( ' xmlns="%s"', $this->xmlns);
00300     }
00301     else if ( isset($this->xmlns) && !isset($nslist[$this->xmlns]) && gettype($this->attributes) == 'array' && !isset($this->attributes[$this->xmlns]) ) {
00302 //      if ( $force_xmlns ) printf( "3: %s: %s\n", $this->tagname, $this->xmlns );
00303       $attr .= sprintf( ' xmlns="%s"', $this->xmlns);
00304     }
00305     else if ( $force_xmlns && isset($this->xmlns) && ! $xmlns_done ) {
00306 //      printf( "4: %s: %s\n", $this->tagname, $this->xmlns );
00307       $attr .= sprintf( ' xmlns="%s"', $this->xmlns);
00308     }
00309     
00310     $r .= substr("                        ",0,$indent) . '<' . $tagname . $attr;
00311 
00312     if ( (is_array($this->content) && count($this->content) > 0) || (!is_array($this->content) && strlen($this->content) > 0) ) {
00313       $r .= ">";
00314       $r .= $this->RenderContent($indent,$nslist,$force_xmlns);
00315       $r .= '</' . $tagname.">\n";
00316     }
00317     else {
00318       $r .= "/>\n";
00319     }
00320     return $r;
00321   }
00322 
00323 
00324   function __tostring() {
00325     return $this->Render();
00326   }
00327 }
00328 
00329 
00338 function BuildXMLTree( $xmltags, &$start_from ) {
00339   $content = array();
00340 
00341   if ( !isset($start_from) ) $start_from = 0;
00342 
00343   for( $i=0; $i < 50000 && isset($xmltags[$start_from]); $i++) {
00344     $tagdata = $xmltags[$start_from++];
00345     if ( !isset($tagdata) || !isset($tagdata['tag']) || !isset($tagdata['type']) ) break;
00346     if ( $tagdata['type'] == "close" ) break;
00347     $xmlns = null;
00348     $tag = $tagdata['tag'];
00349     if ( preg_match( '{^(.*):([^:]*)$}', $tag, $matches) ) {
00350       $xmlns = $matches[1];
00351       $tag = $matches[2];
00352     }
00353     $attributes = ( isset($tagdata['attributes']) ? $tagdata['attributes'] : false );
00354     if ( $tagdata['type'] == "open" ) {
00355       $subtree = BuildXMLTree( $xmltags, $start_from );
00356       $content[] = new XMLElement($tag, $subtree, $attributes, $xmlns );
00357     }
00358     else if ( $tagdata['type'] == "complete" ) {
00359       $value = ( isset($tagdata['value']) ? $tagdata['value'] : false );
00360       $content[] = new XMLElement($tag, $value, $attributes, $xmlns );
00361     }
00362   }
00363 
00368   if ( count($content) == 1 ) {
00369     return $content[0];
00370   }
00371   return $content;
00372 }
00373