Andrew's Web Libraries (AWL)
XMLDocument.php
1<?php
13require_once("XMLElement.php");
14
21
29 private $namespaces;
30
35 private $prefixes;
36
41 private $root;
42
48 function __construct( $namespaces = null ) {
49 $this->namespaces = array();
50 $this->prefixes = array();
51 if ( $namespaces != null ) {
52 foreach( $namespaces AS $ns => $prefix ) {
53 $this->namespaces[$ns] = $prefix;
54 $this->prefixes[$prefix] = $prefix;
55 }
56 }
57 $this->next_prefix = 0;
58 }
59
66 function AddNamespace( $namespace, $prefix = null ) {
67 if ( !isset($this->namespaces[$namespace]) ) {
68 if ( isset($prefix) && ($prefix == "" || isset($this->prefixes[$prefix])) ) $prefix = null;
69 if ( $prefix == null ) {
70 // Try and build a prefix based on the first alphabetic character of the last element of the namespace
71 if ( preg_match('/^(.*):([^:]+)$/', $namespace, $matches) ) {
72 $alpha = preg_replace( '/[^a-z]/i', '', $matches[2] );
73 $prefix = strtoupper(substr($alpha,0,1));
74 }
75 else {
76 $prefix = 'X';
77 }
78 $i = "";
79 if ( isset($this->prefixes[$prefix]) ) {
80 for ( $i=1; $i<10 && isset($this->prefixes["$prefix$i"]); $i++ ) {
81 }
82 }
83 if ( isset($this->prefixes["$prefix$i"]) ) {
84 dbg_error_log("ERROR", "Cannot find a free prefix for this namespace");
85 exit;
86 }
87 $prefix = "$prefix$i";
88 dbg_error_log("XMLDocument", "auto-assigning prefix of '%s' for ns of '%s'", $prefix, $namespace );
89 }
90 else if ( $prefix == "" || isset($this->prefixes[$prefix]) ) {
91 dbg_error_log("ERROR", "Cannot assign the same prefix to two different namespaces");
92 exit;
93 }
94
95 $this->prefixes[$prefix] = $prefix;
96 $this->namespaces[$namespace] = $prefix;
97 }
98 else {
99 if ( isset($this->namespaces[$namespace]) && $this->namespaces[$namespace] != $prefix ) {
100 dbg_error_log("ERROR", "Cannot use the same namespace with two different prefixes");
101 exit;
102 }
103 $this->prefixes[$prefix] = $prefix;
104 $this->namespaces[$namespace] = $prefix;
105 }
106 }
107
111 function DefaultNamespace() {
112 foreach( $this->namespaces AS $k => $v ) {
113 if ( $v == '' ) {
114 return $k;
115 }
116 }
117 return '';
118 }
119
124 function GetXmlNsArray() {
125
126 $ns = array();
127 foreach( $this->namespaces AS $n => $p ) {
128 if ( $p == "" ) $ns["xmlns"] = $n; else $ns["xmlns:$p"] = $n;
129 }
130
131 return $ns;
132 }
133
134
144 function Tag( $in_tag, $namespace=null, $prefix=null ) {
145
146 if ( $namespace == null ) {
147 // Attempt to split out from namespace:tag
148 if ( preg_match('/^(.*):([^:]+)$/', $in_tag, $matches) ) {
149 $namespace = $matches[1];
150 $tag = $matches[2];
151 }
152 else {
153 // There is nothing we can do here
154 return $in_tag;
155 }
156 }
157 else {
158 $tag = $in_tag;
159 }
160
161 if ( !isset($this->namespaces[$namespace]) ) {
162 $this->AddNamespace( $namespace, $prefix );
163 }
164 $prefix = $this->namespaces[$namespace];
165
166 return $prefix . ($prefix == "" ? "" : ":") . $tag;
167 }
168
169 static public $ns_dav = 'DAV:';
170 static public $ns_caldav = 'urn:ietf:params:xml:ns:caldav';
171 static public $ns_carddav = 'urn:ietf:params:xml:ns:carddav';
172 static public $ns_calendarserver = 'http://calendarserver.org/ns/';
173
184 function NSElement( &$element, $in_tag, $content=false, $attributes=false, $namespace=null ) {
185 if ( $namespace == null && preg_match('/^(.*):([^:]+)$/', $in_tag, $matches) ) {
186 $namespace = $matches[1];
187 if ( preg_match('{^[A-Z][A-Z0-9]*$}', $namespace ) ) {
188 throw new Exception("Dodgy looking namespace from '".$in_tag."'!");
189 }
190 $tag = $matches[2];
191 }
192 else {
193 $tag = $in_tag;
194 if ( isset($namespace) ) {
195 $tag = str_replace($namespace.':', '', $tag);
196 }
197 }
198
199 if ( isset($namespace) && !isset($this->namespaces[$namespace]) ) $this->AddNamespace( $namespace );
200 return $element->NewElement( $tag, $content, $attributes, $namespace );
201 }
202
203
212 function DAVElement( &$element, $tag, $content=false, $attributes=false ) {
213 if ( !isset($this->namespaces[self::$ns_dav]) ) $this->AddNamespace( self::$ns_dav, '' );
214 return $this->NSElement( $element, $tag, $content, $attributes, self::$ns_dav );
215 }
216
225 function CalDAVElement( &$element, $tag, $content=false, $attributes=false ) {
226 if ( !isset($this->namespaces[self::$ns_caldav]) ) $this->AddNamespace( self::$ns_caldav, 'C' );
227 return $this->NSElement( $element, $tag, $content, $attributes, self::$ns_caldav );
228 }
229
230
239 function CardDAVElement( &$element, $tag, $content=false, $attributes=false ) {
240 if ( !isset($this->namespaces[self::$ns_carddav]) ) $this->AddNamespace( self::$ns_carddav, 'VC' );
241 return $this->NSElement( $element, $tag, $content, $attributes, self::$ns_carddav );
242 }
243
244
253 function CalendarserverElement( &$element, $tag, $content=false, $attributes=false ) {
254 if ( !isset($this->namespaces[self::$ns_calendarserver]) ) $this->AddNamespace( self::$ns_calendarserver, 'A' );
255 return $this->NSElement( $element, $tag, $content, $attributes, self::$ns_calendarserver );
256 }
257
258
265 function NewXMLElement( $in_tag, $content=false, $attributes=false, $xmlns=null ) {
266 if ( $xmlns == null && preg_match('/^(.*):([^:]+)$/', $in_tag, $matches) ) {
267 $xmlns = $matches[1];
268 $tagname = $matches[2];
269 }
270 else {
271 $tagname = $in_tag;
272 }
273
274 if ( isset($xmlns) && !isset($this->namespaces[$xmlns]) ) $this->AddNamespace( $xmlns );
275 return new XMLElement($tagname, $content, $attributes, $xmlns );
276 }
277
288 function Render( $root, $content=false, $attributes=false, $xmlns=null ) {
289 if ( is_object($root) ) {
291 $this->root = $root;
292 }
293 else {
295 $this->root = $this->NewXMLElement( $root, $content, $attributes, $xmlns );
296 }
297
301 foreach( $this->namespaces AS $n => $p ) {
302 $this->root->SetAttribute( 'xmlns'.($p == '' ? '' : ':') . $p, $n);
303 }
304
306 return $this->root->Render(0,'<?xml version="1.0" encoding="utf-8" ?>');
307 }
308
315 function href($url) {
316 if ( is_array($url) ) {
317 $set = array();
318 foreach( $url AS $href ) {
319 $set[] = $this->href( $href );
320 }
321 return $set;
322 }
323 if ( preg_match('[@+ ]',$url) ) {
324 trace_bug('URL "%s" was not encoded before call to XMLDocument::href()', $url );
325 $url = str_replace( '%2F', '/', rawurlencode($url));
326 }
327 return $this->NewXMLElement('href', $url, false, 'DAV:');
328 }
329
330}
331
332
NewXMLElement( $in_tag, $content=false, $attributes=false, $xmlns=null)
Render( $root, $content=false, $attributes=false, $xmlns=null)
CalendarserverElement(&$element, $tag, $content=false, $attributes=false)
__construct( $namespaces=null)
Definition: XMLDocument.php:48
DAVElement(&$element, $tag, $content=false, $attributes=false)
Tag( $in_tag, $namespace=null, $prefix=null)
NSElement(&$element, $in_tag, $content=false, $attributes=false, $namespace=null)
CardDAVElement(&$element, $tag, $content=false, $attributes=false)
CalDAVElement(&$element, $tag, $content=false, $attributes=false)
AddNamespace( $namespace, $prefix=null)
Definition: XMLDocument.php:66