]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/XmlElement.php
More infiltration of new object-based HTML generation.
[SourceForge/phpwiki.git] / lib / XmlElement.php
1 <?php rcs_id('$Id: XmlElement.php,v 1.2 2002-01-21 06:55:47 dairiki Exp $');
2 /*
3  * Code for writing XML.
4  */
5
6 /**
7  * An XML element.
8  */
9 class XmlElement
10 {
11     function XmlElement ($tagname /* , $attr_or_content , ...*/) {
12         $this->_tag = $tagname;
13         $this->_content = array();
14
15         if (func_num_args() > 1)
16             $this->_init(array_slice(func_get_args(), 1));
17         else 
18             $this->_attr = array();
19     }
20
21     function _init ($args) {
22         assert(is_array($args));
23         if (!$args)
24             return;
25
26         if (is_array($args[0]))
27             $this->_attr = array_shift($args);
28         else {
29             $this->_attr = array();
30             if (count($args) > 1 && ! $args[0])
31                 array_shift($args);
32         }
33
34         if (count($args) == 1 && is_array($args[0]))
35             $this->_content = $args[0];
36         else
37             $this->_content = $args;
38     }
39
40     function getTag () {
41         return $this->_tag;
42     }
43     
44     function setAttr ($attr, $value = false) {
45         if (is_array($attr)) {
46             assert($value === false);
47             foreach ($attr as $a => $v)
48                 $this->set($a, $v);
49             return;
50         }
51
52         assert(is_string($attr));
53         if ($value === false) {
54             unset($this->_attr[$attr]);
55         }
56         if (is_bool($value))
57             $value = $attr;
58         $this->_attr[$attr] = (string) $value;
59     }
60
61     function getAttr ($attr) {
62         if (isset($this->_attr[$attr]))
63             return $this->_attr[$attr];
64         else
65             return false;
66     }
67     
68     function pushContent ($args /*, ...*/) {
69         $c = &$this->_content;
70         if (func_num_args() != 1 || ! is_array($args))
71             $args = func_get_args();
72         array_splice($c, count($c), 0, $args);
73     }
74
75     function unshiftContent ($args /*, ...*/) {
76         $c = &$this->_content;
77         if (func_num_args() != 1 || ! is_array($args))
78             $args = func_get_args();
79         array_splice($c, 0, 0, $args);
80     }
81
82     function getContent () {
83         return $this->_content;
84     }
85
86     function _startTag () {
87         $tag = $this->_tag;
88         foreach ($this->_attr as $attr => $val)
89             $tag .= " $attr=\"" . $this->_quoteAttr($val) . '"';
90         return $tag;
91     }
92
93     function printXML () {
94         if (!$this->_content) {
95             echo "<" . $this->_startTag() . "/>";
96         }
97         else {
98             echo "<" . $this->_startTag() . ">";
99             foreach ($this->_content as $c)
100                 PrintXML($c);
101             echo "</$this->_tag>";
102         }
103     }
104
105     function asXML () {
106         if (!$this->_content) {
107             return "<" . $this->_startTag() . "/>";
108         }
109
110         $xml =  "<" . $this->_startTag() . ">";
111         foreach ($this->_content as $c)
112             $xml .= AsXML($c);
113         $xml .= "</$this->_tag>";
114         return $xml;
115     }
116
117     function asString () {
118         $str = '';
119         foreach ($this->_content as $c)
120             $val .= AsString($c);
121         return trim($str);
122     }
123     
124     function _quote ($string) {
125         return str_replace('<', '&lt;',
126                            str_replace('>', '&gt;',
127                                        str_replace('&', '&amp;', $string)));
128     }
129
130     function _quoteAttr ($value) {
131         return str_replace('"', '&quot;', XmlElement::_quote($value));
132     }
133 };
134
135 class RawXml {
136     function RawXml ($xml_text) {
137         $this->_xml = $xml_text;
138     }
139
140     function printXML () {
141         echo $this->_xml;
142     }
143
144     function asXML () {
145         return $this->_xml;
146     }
147 }
148
149 class FormattedText {
150     function FormattedText ($fs /* , ... */) {
151         if ($fs !== false) {
152             $this->_init(func_get_args());
153         }
154     }
155
156     function _init ($args) {
157         $this->_fs = array_shift($args);
158
159         // PHP's sprintf doesn't support variable width specifiers,
160         // like sprintf("%*s", 10, "x"); --- so we won't either.
161
162         if (! preg_match_all('/(?<!%)%(\d+)\$/x', $this->_fs, $m)) {
163             $this->_args  = $args;
164         }
165         else {
166             // Format string has '%2$s' style argument reordering.
167             // PHP doesn't support this.
168             if (preg_match('/(?<!%)%[- ]?\d*[^- \d$]/x', $fmt))
169                 // literal variable name substitution only to keep locale
170                 // strings uncluttered
171                 trigger_error(sprintf(_("Can't mix '%s' with '%s' type format strings"),
172                                       '%1\$s','%s'), E_USER_WARNING);
173         
174             $this->_fs = preg_replace('/(?<!%)%\d+\$/x', '%', $this->_fs);
175
176             $this->_args = array();
177             foreach($m[1] as $argnum) {
178                 if ($argnum < 1 || $argnum > count($args))
179                     trigger_error(sprintf(_("%s: argument index out of range"), 
180                                           $argnum), E_USER_WARNING);
181                 $this->_args[] = $args[$argnum - 1];
182             }
183         }
184     }
185
186     function asXML () {
187         // Not all PHP's have vsprintf, so...
188         $args[] = XmlElement::_quote($this->_fs);
189         foreach ($this->_args as $arg)
190             $args[] = AsXML($arg);
191         return call_user_func_array('sprintf', $args);
192     }
193
194     function printXML () {
195         // Not all PHP's have vsprintf, so...
196         $args[] = XmlElement::_quote($this->_fs);
197         foreach ($this->_args as $arg)
198             $args[] = AsXML($arg);
199         call_user_func_array('printf', $args);
200     }
201
202     function asString() {
203         $args = $this->_args;
204         array_unshift($args, $this->_fs);
205         return call_user_func_array('sprintf', $args);
206     }
207 }
208
209 function PrintXML ($val) {
210     if (is_object($val)) {
211         if (method_exists($val, 'printxml'))
212             return $val->printXML();
213         elseif (method_exists($val, 'asxml')) {
214             echo $val->asXML();
215             return;
216         }
217         elseif (method_exists($val, 'asstring'))
218             $val = $val->asString();
219     }
220     elseif (is_array($val)) {
221         foreach ($val as $x)
222             PrintXML($x);
223     }
224         
225     echo (string)XmlElement::_quote($val);
226 }
227
228 function AsXML ($val) {
229     if (is_object($val)) {
230         if (method_exists($val, 'asxml'))
231             return $val->asXML();
232         elseif (method_exists($val, 'asstring'))
233             $val = $val->asString();
234     }
235     elseif (is_array($val)) {
236         $xml = '';
237         foreach ($val as $x)
238             $xml .= AsXML($x);
239         return $xml;
240     }
241     
242     return XmlElement::_quote((string)$val);
243 }
244
245 function AsString ($val) {
246     if (can($val, 'asString'))
247         return $val->asString();
248     elseif (is_array($val)) {
249         $str = '';
250         foreach ($val as $x)
251             $str .= AsString($x);
252         return $str;
253     }
254     return (string) $val;
255 }
256
257     
258 function fmt ($fs /* , ... */) {
259     $s = new FormattedText(false);
260
261     $args = func_get_args();
262     $args[0] = gettext($args[0]);
263     $s->_init($args);
264     return $s;
265 }
266     
267 // (c-file-style: "gnu")
268 // Local Variables:
269 // mode: php
270 // tab-width: 8
271 // c-basic-offset: 4
272 // c-hanging-comment-ender-p: nil
273 // indent-tabs-mode: nil
274 // End:   
275 ?>