Andrew's Web Libraries (AWL)
XMLDocument.php
1 <?php
13 require_once("XMLElement.php");
14 
20 class XMLDocument {
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