1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10:
11:
12: require_once('AWLUtilities.php');
13:
14: 15: 16: 17: 18: 19:
20: class XMLElement {
21: protected $tagname;
22: protected $xmlns;
23: protected $attributes;
24: protected $content;
25: protected $_parent;
26:
27: 28: 29: 30: 31: 32: 33: 34:
35: function __construct( $tagname, $content=false, $attributes=false, $xmlns=null ) {
36: $this->tagname=$tagname;
37: if ( gettype($content) == "object" ) {
38:
39: $this->content = array(&$content);
40: }
41: else {
42:
43: $this->content = $content;
44: }
45: $this->attributes = $attributes;
46: if ( isset($xmlns) ) {
47: $this->xmlns = $xmlns;
48: }
49: else {
50: if ( preg_match( '{^(.*):([^:]*)$}', $tagname, $matches) ) {
51: $prefix = $matches[1];
52: $tag = $matches[2];
53: if ( isset($this->attributes['xmlns:'.$prefix]) ) {
54: $this->xmlns = $this->attributes['xmlns:'.$prefix];
55: }
56: }
57: else if ( isset($this->attributes['xmlns']) ) {
58: $this->xmlns = $this->attributes['xmlns'];
59: }
60: }
61: }
62:
63:
64: 65: 66: 67:
68: function CountElements( ) {
69: if ( $this->content === false ) return 0;
70: if ( is_array($this->content) ) return count($this->content);
71: if ( $this->content == '' ) return 0;
72: return 1;
73: }
74:
75: 76: 77: 78: 79: 80:
81: function SetAttribute($k,$v) {
82: if ( gettype($this->attributes) != "array" ) $this->attributes = array();
83: $this->attributes[$k] = $v;
84: if ( strtolower($k) == 'xmlns' ) {
85: $this->xmlns = $v;
86: }
87: }
88:
89: 90: 91: 92: 93:
94: function SetContent($v) {
95: $this->content = $v;
96: }
97:
98: 99: 100: 101: 102:
103: function GetTag() {
104: return $this->tagname;
105: }
106:
107: 108: 109: 110: 111:
112: function GetNSTag() {
113: return (empty($this->xmlns) ? '' : $this->xmlns . ':') . $this->tagname;
114: }
115:
116: 117: 118: 119: 120:
121: function GetAttribute( $attr ) {
122: if ( $attr == 'xmlns' ) return $this->xmlns;
123: if ( isset($this->attributes[$attr]) ) return $this->attributes[$attr];
124: return null;
125: }
126:
127: 128: 129: 130: 131:
132: function GetAttributes() {
133: return $this->attributes;
134: }
135:
136: 137: 138: 139: 140:
141: function GetContent() {
142: return $this->content;
143: }
144:
145: 146: 147: 148: 149: 150:
151: function GetElements( $tag=null, $recursive=false ) {
152: $elements = array();
153: if ( gettype($this->content) == "array" ) {
154: foreach( $this->content AS $k => $v ) {
155: if ( empty($tag) || $v->GetNSTag() == $tag ) {
156: $elements[] = $v;
157: }
158: if ( $recursive ) {
159: $elements = $elements + $v->GetElements($tag,true);
160: }
161: }
162: }
163: else if ( empty($tag) || (isset($v->content->tagname) && $v->content->GetNSTag() == $tag) ) {
164: $elements[] = $this->content;
165: }
166: return $elements;
167: }
168:
169:
170: 171: 172: 173: 174:
175: function GetPath( $path ) {
176: $elements = array();
177:
178: if ( !preg_match( '#(/)?([^/]+)(/?.*)$#', $path, $matches ) ) return $elements;
179:
180: if ( $matches[2] == '*' || $matches[2] == $this->GetNSTag()) {
181: if ( $matches[3] == '' ) {
182: 183: 184:
185: $elements[] = $this;
186: }
187: else if ( gettype($this->content) == "array" ) {
188: 189: 190:
191: foreach( $this->content AS $k => $v ) {
192: $elements = array_merge( $elements, $v->GetPath($matches[3]) );
193: }
194: }
195: }
196:
197: if ( $matches[1] != '/' && gettype($this->content) == "array" ) {
198: 199: 200:
201: foreach( $this->content AS $k => $v ) {
202: $elements = array_merge( $elements, $v->GetPath($path) );
203: }
204: }
205:
206: return $elements;
207: }
208:
209:
210: 211: 212: 213: 214:
215: function AddSubTag(&$v) {
216: if ( gettype($this->content) != "array" ) $this->content = array();
217: $this->content[] =& $v;
218: return count($this->content);
219: }
220:
221: 222: 223: 224: 225: 226: 227: 228: 229:
230: function &NewElement( $tagname, $content=false, $attributes=false, $xmlns=null ) {
231: if ( gettype($this->content) != "array" ) $this->content = array();
232: $element = new XMLElement($tagname,$content,$attributes,$xmlns);
233: $this->content[] =& $element;
234: return $element;
235: }
236:
237:
238: 239: 240: 241: 242:
243: function RenderContent($indent=0, $nslist=null, $force_xmlns=false ) {
244: $r = "";
245: if ( is_array($this->content) ) {
246: 247: 248:
249: $r .= "\n";
250: foreach( $this->content AS $k => $v ) {
251: if ( is_object($v) ) {
252: $r .= $v->Render($indent+1, "", $nslist, $force_xmlns);
253: }
254: }
255: $r .= substr(" ",0,$indent);
256: }
257: else {
258: 259: 260: 261:
262: if(strpos($this->content, '<![CDATA[')===0 && strrpos($this->content, ']]>')===strlen($this->content)-3)
263: $r .= '<![CDATA[' . str_replace(']]>', ']]]]><![CDATA[>', substr($this->content, 9, -3)) . ']]>';
264: else if ( defined('ENT_XML1') && defined('ENT_DISALLOWED') )
265:
266: $r .= htmlspecialchars($this->content, ENT_NOQUOTES | ENT_XML1 | ENT_DISALLOWED );
267:
268:
269:
270: else
271:
272: $r .= htmlspecialchars($this->content, ENT_NOQUOTES );
273: }
274: return $r;
275: }
276:
277:
278: 279: 280: 281: 282:
283: function Render($indent=0, $xmldef="", $nslist=null, $force_xmlns=false) {
284: $r = ( $xmldef == "" ? "" : $xmldef."\n");
285:
286: $attr = "";
287: $tagname = $this->tagname;
288: $xmlns_done = false;
289: if ( gettype($this->attributes) == "array" ) {
290: 291: 292:
293: foreach( $this->attributes AS $k => $v ) {
294: if ( preg_match('#^xmlns(:?(.+))?$#', $k, $matches ) ) {
295:
296: if ( !isset($nslist) ) $nslist = array();
297: $prefix = (isset($matches[2]) ? $matches[2] : '');
298: if ( isset($nslist[$v]) && $nslist[$v] == $prefix ) continue;
299: $nslist[$v] = $prefix;
300: if ( !isset($this->xmlns) ) $this->xmlns = $v;
301: $xmlns_done = true;
302: }
303: $attr .= sprintf( ' %s="%s"', $k, htmlspecialchars($v) );
304: }
305: }
306: if ( isset($this->xmlns) && isset($nslist[$this->xmlns]) && $nslist[$this->xmlns] != '' ) {
307:
308: $tagname = $nslist[$this->xmlns] . ':' . $tagname;
309: if ( $force_xmlns ) $attr .= sprintf( ' xmlns="%s"', $this->xmlns);
310: }
311: else if ( isset($this->xmlns) && !isset($nslist[$this->xmlns]) && gettype($this->attributes) == 'array' && !isset($this->attributes[$this->xmlns]) ) {
312:
313: $attr .= sprintf( ' xmlns="%s"', $this->xmlns);
314: }
315: else if ( $force_xmlns && isset($this->xmlns) && ! $xmlns_done ) {
316:
317: $attr .= sprintf( ' xmlns="%s"', $this->xmlns);
318: }
319:
320: $r .= substr(" ",0,$indent) . '<' . $tagname . $attr;
321:
322: if ( (is_array($this->content) && count($this->content) > 0) || (!is_array($this->content) && strlen($this->content) > 0) ) {
323: $r .= ">";
324: $r .= $this->RenderContent($indent,$nslist,$force_xmlns);
325: $r .= '</' . $tagname.">\n";
326: }
327: else {
328: $r .= "/>\n";
329: }
330: return $r;
331: }
332:
333:
334: function __tostring() {
335: return $this->Render();
336: }
337: }
338:
339:
340: 341: 342: 343: 344: 345: 346: 347:
348: function BuildXMLTree( $xmltags, &$start_from ) {
349: $content = array();
350:
351: if ( !isset($start_from) ) $start_from = 0;
352:
353: for( $i=0; $i < 50000 && isset($xmltags[$start_from]); $i++) {
354: $tagdata = $xmltags[$start_from++];
355: if ( !isset($tagdata) || !isset($tagdata['tag']) || !isset($tagdata['type']) ) break;
356: if ( $tagdata['type'] == "close" ) break;
357: $xmlns = null;
358: $tag = $tagdata['tag'];
359: if ( preg_match( '{^(.*):([^:]*)$}', $tag, $matches) ) {
360: $xmlns = $matches[1];
361: $tag = $matches[2];
362: }
363: $attributes = ( isset($tagdata['attributes']) ? $tagdata['attributes'] : false );
364: if ( $tagdata['type'] == "open" ) {
365: $subtree = BuildXMLTree( $xmltags, $start_from );
366: $content[] = new XMLElement($tag, $subtree, $attributes, $xmlns );
367: }
368: else if ( $tagdata['type'] == "complete" ) {
369: $value = ( isset($tagdata['value']) ? $tagdata['value'] : false );
370: $content[] = new XMLElement($tag, $value, $attributes, $xmlns );
371: }
372: }
373:
374: 375: 376: 377:
378: if ( count($content) == 1 ) {
379: return $content[0];
380: }
381: return $content;
382: }
383:
384: