]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/XmlElement.php
Fix/add isEmpty() methods of XmlElement and RawXml.
[SourceForge/phpwiki.git] / lib / XmlElement.php
1 <?php rcs_id('$Id: XmlElement.php,v 1.14 2002-01-27 22:06:38 dairiki Exp $');
2 /*
3  * Code for writing XML.
4  */
5
6 /**
7  * An XML element.
8  *
9  * @param $tagname string Tag of html element.
10  *
11  * If $tagname is set to <code>false</code> you get a fake element with no start
12  * or end tag, (just content, if any).  This is useful for creating a single
13  * quasi-element object, which contains a number of other elements.
14  */
15 class XmlElement
16 {
17     function XmlElement ($tagname /* , $attr_or_content , ...*/) {
18         $this->_init(func_get_args());
19     }
20
21     function _init ($args) {
22         if (!is_array($args))
23             $args = func_get_args();
24
25         assert(count($args) >= 1);
26         //assert(is_string($args[0]));
27         $this->_tag = array_shift($args);
28
29         if ($args && is_array($args[0]))
30             $this->_attr = array_shift($args);
31         else {
32             $this->_attr = array();
33             if (count($args) > 1 && ! $args[0])
34                 array_shift($args);
35         }
36
37         if (count($args) == 1 && is_array($args[0]))
38             $args = $args[0];
39         $this->_content = $args;
40     }
41
42     function getTag () {
43         return $this->_tag;
44     }
45     
46     function setAttr ($attr, $value = false) {
47         if (is_array($attr)) {
48             assert($value === false);
49             foreach ($attr as $a => $v)
50                 $this->set($a, $v);
51             return;
52         }
53
54         assert(is_string($attr));
55         if ($value === false) {
56             unset($this->_attr[$attr]);
57         }
58         if (is_bool($value))
59             $value = $attr;
60         $this->_attr[$attr] = (string) $value;
61     }
62
63     function getAttr ($attr) {
64         if (isset($this->_attr[$attr]))
65             return $this->_attr[$attr];
66         else
67             return false;
68     }
69     
70     function pushContent ($args /*, ...*/) {
71         $c = &$this->_content;
72         if (func_num_args() != 1 || ! is_array($args))
73             $args = func_get_args();
74         array_splice($c, count($c), 0, $args);
75     }
76
77     function unshiftContent ($args /*, ...*/) {
78         $c = &$this->_content;
79         if (func_num_args() != 1 || ! is_array($args))
80             $args = func_get_args();
81         array_splice($c, 0, 0, $args);
82     }
83
84     function getContent () {
85         return $this->_content;
86     }
87
88     /**
89      * @access private
90      */
91     function _startTag() {
92         $start = "<" . $this->_tag;
93         foreach ($this->_attr as $attr => $val) {
94             if (is_bool($val)) {
95                 if (!$val)
96                     continue;
97                 $val = $attr;
98             }
99             $start .= " $attr=\"" . $this->_quoteAttr($val) . "\"";
100         }
101         $start .= ">";
102         return $start;
103     }
104
105     /**
106      * @access private
107      */
108     function _emptyTag() {
109         return substr($this->_startTag(), 0, -1) . "/>";
110     }
111
112     function startTag() {
113         return $this->_tag ? $this->_startTag() : '';
114     }
115     
116     function endTag() {
117         return $this->_tag ? "</$this->_tag>" : '';
118     }
119     
120         
121     function printXML () {
122         
123         if (! $this->_content) {
124             if ($this->_tag)
125                 echo $this->_emptyTag();
126         }
127         else {
128             $sep = $this->hasInlineContent() ? "" : "\n";
129             if ($this->_tag)
130                 echo $this->_startTag() . $sep;
131             foreach ($this->_content as $c) {
132                 PrintXML($c);
133                 echo $sep;
134             }
135             if ($this->_tag)
136                 echo "</$this->_tag>";
137         }
138     }
139
140     function asXML () {
141         if (! $this->_content)
142             return $this->_tag ? $this->_emptyTag() : '';
143
144         $sep = $this->hasInlineContent() ? "" : "\n";
145         $xml = '';
146         if ($this->_tag)
147             $xml .= $this->_startTag() . $sep;
148         foreach ($this->_content as $c)
149             $xml .= AsXML($c) . $sep;
150         if ($this->_tag)
151             $xml .= "</$this->_tag>";
152         return $xml;
153     }
154
155     function asString () {
156         $str = '';
157         foreach ($this->_content as $c)
158             $str .= AsString($c);
159         return trim($str);
160     }
161
162     /**
163      * See if element is empty.
164      *
165      * Empty means it has no content.
166      * @return bool True if empty.
167      *
168      * Bugs: This fails if any of the content is itself an empty array.
169      * We might want to fix things so that content gets flattend by
170      * {push,unshift}Content, rather than by {print,as}XML.
171      */
172     function isEmpty () {
173         if (empty($this->_content))
174             return true;
175         foreach ($this->_content as $x) {
176             if (!empty($x))
177                 return false;
178         }
179         return true;
180     }
181
182     function hasInlineContent () {
183         // FIXME: This is a hack.
184         if (empty($this->_content))
185             return false;
186         if (is_object($this->_content[0]))
187             return false;
188         return true;
189     }
190     
191     function _quote ($string) {
192         return str_replace('<', '&lt;',
193                            str_replace('>', '&gt;',
194                                        str_replace('&', '&amp;', $string)));
195     }
196
197     function _quoteAttr ($value) {
198         return str_replace('"', '&quot;', XmlElement::_quote($value));
199         //"<--kludge for brain-dead syntax coloring
200     }
201 };
202
203 class RawXml {
204     function RawXml ($xml_text) {
205         $this->_xml = $xml_text;
206     }
207
208     function printXML () {
209         echo $this->_xml;
210     }
211
212     function asXML () {
213         return $this->_xml;
214     }
215
216     function isEmpty () {
217         return empty($this->_xml);
218     }
219 }
220
221 class FormattedText {
222     function FormattedText ($fs /* , ... */) {
223         if ($fs !== false) {
224             $this->_init(func_get_args());
225         }
226     }
227
228     function _init ($args) {
229         $this->_fs = array_shift($args);
230
231         // PHP's sprintf doesn't support variable width specifiers,
232         // like sprintf("%*s", 10, "x"); --- so we won't either.
233
234         if (! preg_match_all('/(?<!%)%(\d+)\$/x', $this->_fs, $m)) {
235             $this->_args  = $args;
236         }
237         else {
238             // Format string has '%2$s' style argument reordering.
239             // PHP doesn't support this.
240             if (preg_match('/(?<!%)%[- ]?\d*[^- \d$]/x', $fmt))
241                 // literal variable name substitution only to keep locale
242                 // strings uncluttered
243                 trigger_error(sprintf(_("Can't mix '%s' with '%s' type format strings"),
244                                       '%1\$s','%s'), E_USER_WARNING);
245         
246             $this->_fs = preg_replace('/(?<!%)%\d+\$/x', '%', $this->_fs);
247
248             $this->_args = array();
249             foreach($m[1] as $argnum) {
250                 if ($argnum < 1 || $argnum > count($args))
251                     trigger_error(sprintf("%s: argument index out of range", 
252                                           $argnum), E_USER_WARNING);
253                 $this->_args[] = $args[$argnum - 1];
254             }
255         }
256     }
257
258     function asXML () {
259         // Not all PHP's have vsprintf, so...
260         $args[] = XmlElement::_quote($this->_fs);
261         foreach ($this->_args as $arg)
262             $args[] = AsXML($arg);
263         return call_user_func_array('sprintf', $args);
264     }
265
266     function printXML () {
267         // Not all PHP's have vsprintf, so...
268         $args[] = XmlElement::_quote($this->_fs);
269         foreach ($this->_args as $arg)
270             $args[] = AsXML($arg);
271         call_user_func_array('printf', $args);
272     }
273
274     function asString() {
275         $args[] = $this->_fs;
276         foreach ($this->_args as $arg)
277             $args[] = AsString($arg);
278         return call_user_func_array('sprintf', $args);
279     }
280 }
281
282 function PrintXML ($val) {
283     if (is_object($val)) {
284         if (method_exists($val, 'printxml'))
285             return $val->printXML();
286         elseif (method_exists($val, 'asxml')) {
287             echo $val->asXML();
288             return;
289         }
290         elseif (method_exists($val, 'asstring'))
291             $val = $val->asString();
292     }
293     elseif (is_array($val)) {
294         foreach ($val as $x)
295             PrintXML($x);
296         return;
297     }
298         
299     echo (string)XmlElement::_quote($val);
300 }
301
302 function AsXML ($val) {
303     if (is_object($val)) {
304         if (method_exists($val, 'asxml'))
305             return $val->asXML();
306         elseif (method_exists($val, 'asstring'))
307             $val = $val->asString();
308     }
309     elseif (is_array($val)) {
310         $xml = '';
311         foreach ($val as $x)
312             $xml .= AsXML($x);
313         return $xml;
314     }
315     
316     return XmlElement::_quote((string)$val);
317 }
318
319 function AsString ($val) {
320     if (can($val, 'asString'))
321         return $val->asString();
322     elseif (is_array($val)) {
323         $str = '';
324         foreach ($val as $x)
325             $str .= AsString($x);
326         return $str;
327     }
328     
329     return (string) $val;
330 }
331
332
333     
334 function fmt ($fs /* , ... */) {
335     $s = new FormattedText(false);
336
337     $args = func_get_args();
338     $args[0] = _($args[0]);
339     $s->_init($args);
340     return $s;
341 }
342     
343 // (c-file-style: "gnu")
344 // Local Variables:
345 // mode: php
346 // tab-width: 8
347 // c-basic-offset: 4
348 // c-hanging-comment-ender-p: nil
349 // indent-tabs-mode: nil
350 // End:   
351 ?>