Subversion Repositories Applications.papyrus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1278 neiluj 1
<?PHP
2
/* vim: set expandtab tabstop=4 shiftwidth=4: */
3
// +----------------------------------------------------------------------+
4
// | PHP Version 4                                                        |
5
// +----------------------------------------------------------------------+
6
// | Copyright (c) 1997-2002 The PHP Group                                |
7
// +----------------------------------------------------------------------+
8
// | This source file is subject to version 2.0 of the PHP license,       |
9
// | that is bundled with this package in the file LICENSE, and is        |
10
// | available at through the world-wide-web at                           |
11
// | http://www.php.net/license/2_02.txt.                                 |
12
// | If you did not receive a copy of the PHP license and are unable to   |
13
// | obtain it through the world-wide-web, please send a note to          |
14
// | license@php.net so we can mail you a copy immediately.               |
15
// +----------------------------------------------------------------------+
16
// | Authors: Stephan Schmidt <schst@php-tools.net>                       |
17
// +----------------------------------------------------------------------+
18
//
19
//    $Id: Util.php,v 1.1 2007-03-28 08:51:22 neiluj Exp $
20
 
21
/**
22
 * error code for invalid chars in XML name
23
 */
24
define("XML_UTIL_ERROR_INVALID_CHARS", 51);
25
 
26
/**
27
 * error code for invalid chars in XML name
28
 */
29
define("XML_UTIL_ERROR_INVALID_START", 52);
30
 
31
/**
32
 * error code for non-scalar tag content
33
 */
34
define("XML_UTIL_ERROR_NON_SCALAR_CONTENT", 60);
35
 
36
/**
37
 * error code for missing tag name
38
 */
39
define("XML_UTIL_ERROR_NO_TAG_NAME", 61);
40
 
41
/**
42
 * replace XML entities
43
 */
44
define("XML_UTIL_REPLACE_ENTITIES", 1);
45
 
46
/**
47
 * embedd content in a CData Section
48
 */
49
define("XML_UTIL_CDATA_SECTION", 5);
50
 
51
/**
52
 * do not replace entitites
53
 */
54
define("XML_UTIL_ENTITIES_NONE", 0);
55
 
56
/**
57
 * replace all XML entitites
58
 * This setting will replace <, >, ", ' and &
59
 */
60
define("XML_UTIL_ENTITIES_XML", 1);
61
 
62
/**
63
 * replace only required XML entitites
64
 * This setting will replace <, " and &
65
 */
66
define("XML_UTIL_ENTITIES_XML_REQUIRED", 2);
67
 
68
/**
69
 * replace HTML entitites
70
 * @link    http://www.php.net/htmlentities
71
 */
72
define("XML_UTIL_ENTITIES_HTML", 3);
73
 
74
/**
75
 * Collapse all empty tags.
76
 */
77
define("XML_UTIL_COLLAPSE_ALL", 1);
78
 
79
/**
80
 * Collapse only empty XHTML tags that have no end tag.
81
 */
82
define("XML_UTIL_COLLAPSE_XHTML_ONLY", 2);
83
 
84
/**
85
 * utility class for working with XML documents
86
 *
87
 * @category XML
88
 * @package  XML_Util
89
 * @version  1.1.0
90
 * @author   Stephan Schmidt <schst@php.net>
91
 */
92
class XML_Util {
93
 
94
   /**
95
    * return API version
96
    *
97
    * @access   public
98
    * @static
99
    * @return   string  $version API version
100
    */
101
    function apiVersion()
102
    {
103
        return '1.1';
104
    }
105
 
106
   /**
107
    * replace XML entities
108
    *
109
    * With the optional second parameter, you may select, which
110
    * entities should be replaced.
111
    *
112
    * <code>
113
    * require_once 'XML/Util.php';
114
    *
115
    * // replace XML entites:
116
    * $string = XML_Util::replaceEntities("This string contains < & >.");
117
    * </code>
118
    *
119
    * @access   public
120
    * @static
121
    * @param    string  string where XML special chars should be replaced
122
    * @param    integer setting for entities in attribute values (one of XML_UTIL_ENTITIES_XML, XML_UTIL_ENTITIES_XML_REQUIRED, XML_UTIL_ENTITIES_HTML)
123
    * @return   string  string with replaced chars
124
    * @see      reverseEntities()
125
    */
126
    function replaceEntities($string, $replaceEntities = XML_UTIL_ENTITIES_XML)
127
    {
128
        switch ($replaceEntities) {
129
            case XML_UTIL_ENTITIES_XML:
130
                return strtr($string,array(
131
                                          '&'  => '&amp;',
132
                                          '>'  => '&gt;',
133
                                          '<'  => '&lt;',
134
                                          '"'  => '&quot;',
135
                                          '\'' => '&apos;' ));
136
                break;
137
            case XML_UTIL_ENTITIES_XML_REQUIRED:
138
                return strtr($string,array(
139
                                          '&'  => '&amp;',
140
                                          '<'  => '&lt;',
141
                                          '"'  => '&quot;' ));
142
                break;
143
            case XML_UTIL_ENTITIES_HTML:
144
                return htmlentities($string);
145
                break;
146
        }
147
        return $string;
148
    }
149
 
150
   /**
151
    * reverse XML entities
152
    *
153
    * With the optional second parameter, you may select, which
154
    * entities should be reversed.
155
    *
156
    * <code>
157
    * require_once 'XML/Util.php';
158
    *
159
    * // reverse XML entites:
160
    * $string = XML_Util::reverseEntities("This string contains &lt; &amp; &gt;.");
161
    * </code>
162
    *
163
    * @access   public
164
    * @static
165
    * @param    string  string where XML special chars should be replaced
166
    * @param    integer setting for entities in attribute values (one of XML_UTIL_ENTITIES_XML, XML_UTIL_ENTITIES_XML_REQUIRED, XML_UTIL_ENTITIES_HTML)
167
    * @return   string  string with replaced chars
168
    * @see      replaceEntities()
169
    */
170
    function reverseEntities($string, $replaceEntities = XML_UTIL_ENTITIES_XML)
171
    {
172
        switch ($replaceEntities) {
173
            case XML_UTIL_ENTITIES_XML:
174
                return strtr($string,array(
175
                                          '&amp;'  => '&',
176
                                          '&gt;'   => '>',
177
                                          '&lt;'   => '<',
178
                                          '&quot;' => '"',
179
                                          '&apos;' => '\'' ));
180
                break;
181
            case XML_UTIL_ENTITIES_XML_REQUIRED:
182
                return strtr($string,array(
183
                                          '&amp;'  => '&',
184
                                          '&lt;'   => '<',
185
                                          '&quot;' => '"' ));
186
                break;
187
            case XML_UTIL_ENTITIES_HTML:
188
                $arr = array_flip(get_html_translation_table(HTML_ENTITIES));
189
                return strtr($string, $arr);
190
                break;
191
        }
192
        return $string;
193
    }
194
 
195
   /**
196
    * build an xml declaration
197
    *
198
    * <code>
199
    * require_once 'XML/Util.php';
200
    *
201
    * // get an XML declaration:
202
    * $xmlDecl = XML_Util::getXMLDeclaration("1.0", "UTF-8", true);
203
    * </code>
204
    *
205
    * @access   public
206
    * @static
207
    * @param    string  $version     xml version
208
    * @param    string  $encoding    character encoding
209
    * @param    boolean $standAlone  document is standalone (or not)
210
    * @return   string  $decl xml declaration
211
    * @uses     XML_Util::attributesToString() to serialize the attributes of the XML declaration
212
    */
213
    function getXMLDeclaration($version = "1.0", $encoding = null, $standalone = null)
214
    {
215
        $attributes = array(
216
                            "version" => $version,
217
                           );
218
        // add encoding
219
        if ($encoding !== null) {
220
            $attributes["encoding"] = $encoding;
221
        }
222
        // add standalone, if specified
223
        if ($standalone !== null) {
224
            $attributes["standalone"] = $standalone ? "yes" : "no";
225
        }
226
 
227
        return sprintf("<?xml%s?>", XML_Util::attributesToString($attributes, false));
228
    }
229
 
230
   /**
231
    * build a document type declaration
232
    *
233
    * <code>
234
    * require_once 'XML/Util.php';
235
    *
236
    * // get a doctype declaration:
237
    * $xmlDecl = XML_Util::getDocTypeDeclaration("rootTag","myDocType.dtd");
238
    * </code>
239
    *
240
    * @access   public
241
    * @static
242
    * @param    string  $root         name of the root tag
243
    * @param    string  $uri          uri of the doctype definition (or array with uri and public id)
244
    * @param    string  $internalDtd  internal dtd entries
245
    * @return   string  $decl         doctype declaration
246
    * @since    0.2
247
    */
248
    function getDocTypeDeclaration($root, $uri = null, $internalDtd = null)
249
    {
250
        if (is_array($uri)) {
251
            $ref = sprintf( ' PUBLIC "%s" "%s"', $uri["id"], $uri["uri"] );
252
        } elseif (!empty($uri)) {
253
            $ref = sprintf( ' SYSTEM "%s"', $uri );
254
        } else {
255
            $ref = "";
256
        }
257
 
258
        if (empty($internalDtd)) {
259
            return sprintf("<!DOCTYPE %s%s>", $root, $ref);
260
        } else {
261
            return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
262
        }
263
    }
264
 
265
   /**
266
    * create string representation of an attribute list
267
    *
268
    * <code>
269
    * require_once 'XML/Util.php';
270
    *
271
    * // build an attribute string
272
    * $att = array(
273
    *              "foo"   =>  "bar",
274
    *              "argh"  =>  "tomato"
275
    *            );
276
    *
277
    * $attList = XML_Util::attributesToString($att);
278
    * </code>
279
    *
280
    * @access   public
281
    * @static
282
    * @param    array         $attributes        attribute array
283
    * @param    boolean|array $sort              sort attribute list alphabetically, may also be an assoc array containing the keys 'sort', 'multiline', 'indent', 'linebreak' and 'entities'
284
    * @param    boolean       $multiline         use linebreaks, if more than one attribute is given
285
    * @param    string        $indent            string used for indentation of multiline attributes
286
    * @param    string        $linebreak         string used for linebreaks of multiline attributes
287
    * @param    integer       $entities          setting for entities in attribute values (one of XML_UTIL_ENTITIES_NONE, XML_UTIL_ENTITIES_XML, XML_UTIL_ENTITIES_XML_REQUIRED, XML_UTIL_ENTITIES_HTML)
288
    * @return   string                           string representation of the attributes
289
    * @uses     XML_Util::replaceEntities() to replace XML entities in attribute values
290
    * @todo     allow sort also to be an options array
291
    */
292
    function attributesToString($attributes, $sort = true, $multiline = false, $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML)
293
    {
294
        /**
295
         * second parameter may be an array
296
         */
297
        if (is_array($sort)) {
298
            if (isset($sort['multiline'])) {
299
                $multiline = $sort['multiline'];
300
            }
301
            if (isset($sort['indent'])) {
302
                $indent = $sort['indent'];
303
            }
304
            if (isset($sort['linebreak'])) {
305
                $multiline = $sort['linebreak'];
306
            }
307
            if (isset($sort['entities'])) {
308
                $entities = $sort['entities'];
309
            }
310
            if (isset($sort['sort'])) {
311
                $sort = $sort['sort'];
312
            } else {
313
                $sort = true;
314
            }
315
        }
316
        $string = '';
317
        if (is_array($attributes) && !empty($attributes)) {
318
            if ($sort) {
319
                ksort($attributes);
320
            }
321
            if( !$multiline || count($attributes) == 1) {
322
                foreach ($attributes as $key => $value) {
323
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
324
                        if ($entities === XML_UTIL_CDATA_SECTION) {
325
                        	$entities = XML_UTIL_ENTITIES_XML;
326
                        }
327
                        $value = XML_Util::replaceEntities($value, $entities);
328
                    }
329
                    $string .= ' '.$key.'="'.$value.'"';
330
                }
331
            } else {
332
                $first = true;
333
                foreach ($attributes as $key => $value) {
334
                    if ($entities != XML_UTIL_ENTITIES_NONE) {
335
                        $value = XML_Util::replaceEntities($value, $entities);
336
                    }
337
                    if ($first) {
338
                        $string .= " ".$key.'="'.$value.'"';
339
                        $first = false;
340
                    } else {
341
                        $string .= $linebreak.$indent.$key.'="'.$value.'"';
342
                    }
343
                }
344
            }
345
        }
346
        return $string;
347
    }
348
 
349
   /**
350
    * Collapses empty tags.
351
    *
352
    * @access   public
353
    * @static
354
    * @param    string  $xml  XML
355
    * @param    integer $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL) or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
356
    * @return   string  $xml  XML
357
    */
358
    function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL) {
359
        if ($mode == XML_UTIL_COLLAPSE_XHTML_ONLY) {
360
            return preg_replace(
361
              '/<(area|base|br|col|hr|img|input|link|meta|param)([^>]*)><\/\\1>/s',
362
              '<\\1\\2 />',
363
              $xml
364
            );
365
        } else {
366
            return preg_replace(
367
              '/<(\w+)([^>]*)><\/\\1>/s',
368
              '<\\1\\2 />',
369
              $xml
370
            );
371
        }
372
    }
373
 
374
   /**
375
    * create a tag
376
    *
377
    * This method will call XML_Util::createTagFromArray(), which
378
    * is more flexible.
379
    *
380
    * <code>
381
    * require_once 'XML/Util.php';
382
    *
383
    * // create an XML tag:
384
    * $tag = XML_Util::createTag("myNs:myTag", array("foo" => "bar"), "This is inside the tag", "http://www.w3c.org/myNs#");
385
    * </code>
386
    *
387
    * @access   public
388
    * @static
389
    * @param    string  $qname             qualified tagname (including namespace)
390
    * @param    array   $attributes        array containg attributes
391
    * @param    mixed   $content
392
    * @param    string  $namespaceUri      URI of the namespace
393
    * @param    integer $replaceEntities   whether to replace XML special chars in content, embedd it in a CData section or none of both
394
    * @param    boolean $multiline         whether to create a multiline tag where each attribute gets written to a single line
395
    * @param    string  $indent            string used to indent attributes (_auto indents attributes so they start at the same column)
396
    * @param    string  $linebreak         string used for linebreaks
397
    * @param    boolean $sortAttributes    Whether to sort the attributes or not
398
    * @return   string  $string            XML tag
399
    * @see      XML_Util::createTagFromArray()
400
    * @uses     XML_Util::createTagFromArray() to create the tag
401
    */
402
    function createTag($qname, $attributes = array(), $content = null, $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n", $sortAttributes = true)
403
    {
404
        $tag = array(
405
                     "qname"      => $qname,
406
                     "attributes" => $attributes
407
                    );
408
 
409
        // add tag content
410
        if ($content !== null) {
411
            $tag["content"] = $content;
412
        }
413
 
414
        // add namespace Uri
415
        if ($namespaceUri !== null) {
416
            $tag["namespaceUri"] = $namespaceUri;
417
        }
418
 
419
        return XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $linebreak, $sortAttributes);
420
    }
421
 
422
   /**
423
    * create a tag from an array
424
    * this method awaits an array in the following format
425
    * <pre>
426
    * array(
427
    *  "qname"        => $qname         // qualified name of the tag
428
    *  "namespace"    => $namespace     // namespace prefix (optional, if qname is specified or no namespace)
429
    *  "localpart"    => $localpart,    // local part of the tagname (optional, if qname is specified)
430
    *  "attributes"   => array(),       // array containing all attributes (optional)
431
    *  "content"      => $content,      // tag content (optional)
432
    *  "namespaceUri" => $namespaceUri  // namespaceUri for the given namespace (optional)
433
    *   )
434
    * </pre>
435
    *
436
    * <code>
437
    * require_once 'XML/Util.php';
438
    *
439
    * $tag = array(
440
    *           "qname"        => "foo:bar",
441
    *           "namespaceUri" => "http://foo.com",
442
    *           "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
443
    *           "content"      => "I'm inside the tag",
444
    *            );
445
    * // creating a tag with qualified name and namespaceUri
446
    * $string = XML_Util::createTagFromArray($tag);
447
    * </code>
448
    *
449
    * @access   public
450
    * @static
451
    * @param    array   $tag               tag definition
452
    * @param    integer $replaceEntities   whether to replace XML special chars in content, embedd it in a CData section or none of both
453
    * @param    boolean $multiline         whether to create a multiline tag where each attribute gets written to a single line
454
    * @param    string  $indent            string used to indent attributes (_auto indents attributes so they start at the same column)
455
    * @param    string  $linebreak         string used for linebreaks
456
    * @param    boolean $sortAttributes    Whether to sort the attributes or not
457
    * @return   string  $string            XML tag
458
    * @see      XML_Util::createTag()
459
    * @uses     XML_Util::attributesToString() to serialize the attributes of the tag
460
    * @uses     XML_Util::splitQualifiedName() to get local part and namespace of a qualified name
461
    */
462
    function createTagFromArray($tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n", $sortAttributes = true)
463
    {
464
        if (isset($tag['content']) && !is_scalar($tag['content'])) {
465
            return XML_Util::raiseError( 'Supplied non-scalar value as tag content', XML_UTIL_ERROR_NON_SCALAR_CONTENT );
466
        }
467
 
468
        if (!isset($tag['qname']) && !isset($tag['localPart'])) {
469
            return XML_Util::raiseError( 'You must either supply a qualified name (qname) or local tag name (localPart).', XML_UTIL_ERROR_NO_TAG_NAME );
470
        }
471
 
472
        // if no attributes hav been set, use empty attributes
473
        if (!isset($tag["attributes"]) || !is_array($tag["attributes"])) {
474
            $tag["attributes"] = array();
475
        }
476
 
477
        if (isset($tag['namespaces'])) {
478
        	foreach ($tag['namespaces'] as $ns => $uri) {
479
                $tag['attributes']['xmlns:'.$ns] = $uri;
480
        	}
481
        }
482
 
483
        // qualified name is not given
484
        if (!isset($tag["qname"])) {
485
            // check for namespace
486
            if (isset($tag["namespace"]) && !empty($tag["namespace"])) {
487
                $tag["qname"] = $tag["namespace"].":".$tag["localPart"];
488
            } else {
489
                $tag["qname"] = $tag["localPart"];
490
            }
491
        // namespace URI is set, but no namespace
492
        } elseif (isset($tag["namespaceUri"]) && !isset($tag["namespace"])) {
493
            $parts = XML_Util::splitQualifiedName($tag["qname"]);
494
            $tag["localPart"] = $parts["localPart"];
495
            if (isset($parts["namespace"])) {
496
                $tag["namespace"] = $parts["namespace"];
497
            }
498
        }
499
 
500
        if (isset($tag["namespaceUri"]) && !empty($tag["namespaceUri"])) {
501
            // is a namespace given
502
            if (isset($tag["namespace"]) && !empty($tag["namespace"])) {
503
                $tag["attributes"]["xmlns:".$tag["namespace"]] = $tag["namespaceUri"];
504
            } else {
505
                // define this Uri as the default namespace
506
                $tag["attributes"]["xmlns"] = $tag["namespaceUri"];
507
            }
508
        }
509
 
510
        // check for multiline attributes
511
        if ($multiline === true) {
512
            if ($indent === "_auto") {
513
                $indent = str_repeat(" ", (strlen($tag["qname"])+2));
514
            }
515
        }
516
 
517
        // create attribute list
518
        $attList    =   XML_Util::attributesToString($tag['attributes'], $sortAttributes, $multiline, $indent, $linebreak, $replaceEntities );
519
        if (!isset($tag['content']) || (string)$tag['content'] == '') {
520
            $tag    =   sprintf('<%s%s />', $tag['qname'], $attList);
521
        } else {
522
            switch ($replaceEntities) {
523
                case XML_UTIL_ENTITIES_NONE:
524
                    break;
525
                case XML_UTIL_CDATA_SECTION:
526
                    $tag['content'] = XML_Util::createCDataSection($tag['content']);
527
                    break;
528
                default:
529
                    $tag['content'] = XML_Util::replaceEntities($tag['content'], $replaceEntities);
530
                    break;
531
            }
532
            $tag    =   sprintf('<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'], $tag['qname'] );
533
        }
534
        return  $tag;
535
    }
536
 
537
   /**
538
    * create a start element
539
    *
540
    * <code>
541
    * require_once 'XML/Util.php';
542
    *
543
    * // create an XML start element:
544
    * $tag = XML_Util::createStartElement("myNs:myTag", array("foo" => "bar") ,"http://www.w3c.org/myNs#");
545
    * </code>
546
    *
547
    * @access   public
548
    * @static
549
    * @param    string  $qname             qualified tagname (including namespace)
550
    * @param    array   $attributes        array containg attributes
551
    * @param    string  $namespaceUri      URI of the namespace
552
    * @param    boolean $multiline         whether to create a multiline tag where each attribute gets written to a single line
553
    * @param    string  $indent            string used to indent attributes (_auto indents attributes so they start at the same column)
554
    * @param    string  $linebreak         string used for linebreaks
555
    * @param    boolean $sortAttributes    Whether to sort the attributes or not
556
    * @return   string  $string            XML start element
557
    * @see      XML_Util::createEndElement(), XML_Util::createTag()
558
    */
559
    function createStartElement($qname, $attributes = array(), $namespaceUri = null, $multiline = false, $indent = '_auto', $linebreak = "\n", $sortAttributes = true)
560
    {
561
        // if no attributes hav been set, use empty attributes
562
        if (!isset($attributes) || !is_array($attributes)) {
563
            $attributes = array();
564
        }
565
 
566
        if ($namespaceUri != null) {
567
            $parts = XML_Util::splitQualifiedName($qname);
568
        }
569
 
570
        // check for multiline attributes
571
        if ($multiline === true) {
572
            if ($indent === "_auto") {
573
                $indent = str_repeat(" ", (strlen($qname)+2));
574
            }
575
        }
576
 
577
        if ($namespaceUri != null) {
578
            // is a namespace given
579
            if (isset($parts["namespace"]) && !empty($parts["namespace"])) {
580
                $attributes["xmlns:".$parts["namespace"]] = $namespaceUri;
581
            } else {
582
                // define this Uri as the default namespace
583
                $attributes["xmlns"] = $namespaceUri;
584
            }
585
        }
586
 
587
        // create attribute list
588
        $attList    =   XML_Util::attributesToString($attributes, $sortAttributes, $multiline, $indent, $linebreak);
589
        $element    =   sprintf("<%s%s>", $qname, $attList);
590
        return  $element;
591
    }
592
 
593
   /**
594
    * create an end element
595
    *
596
    * <code>
597
    * require_once 'XML/Util.php';
598
    *
599
    * // create an XML start element:
600
    * $tag = XML_Util::createEndElement("myNs:myTag");
601
    * </code>
602
    *
603
    * @access   public
604
    * @static
605
    * @param    string  $qname             qualified tagname (including namespace)
606
    * @return   string  $string            XML end element
607
    * @see      XML_Util::createStartElement(), XML_Util::createTag()
608
    */
609
    function createEndElement($qname)
610
    {
611
        $element    =   sprintf("</%s>", $qname);
612
        return  $element;
613
    }
614
 
615
   /**
616
    * create an XML comment
617
    *
618
    * <code>
619
    * require_once 'XML/Util.php';
620
    *
621
    * // create an XML start element:
622
    * $tag = XML_Util::createComment("I am a comment");
623
    * </code>
624
    *
625
    * @access   public
626
    * @static
627
    * @param    string  $content           content of the comment
628
    * @return   string  $comment           XML comment
629
    */
630
    function createComment($content)
631
    {
632
        $comment    =   sprintf("<!-- %s -->", $content);
633
        return  $comment;
634
    }
635
 
636
   /**
637
    * create a CData section
638
    *
639
    * <code>
640
    * require_once 'XML/Util.php';
641
    *
642
    * // create a CData section
643
    * $tag = XML_Util::createCDataSection("I am content.");
644
    * </code>
645
    *
646
    * @access   public
647
    * @static
648
    * @param    string  $data              data of the CData section
649
    * @return   string  $string            CData section with content
650
    */
651
    function createCDataSection($data)
652
    {
653
        return  sprintf("<![CDATA[%s]]>", $data);
654
    }
655
 
656
   /**
657
    * split qualified name and return namespace and local part
658
    *
659
    * <code>
660
    * require_once 'XML/Util.php';
661
    *
662
    * // split qualified tag
663
    * $parts = XML_Util::splitQualifiedName("xslt:stylesheet");
664
    * </code>
665
    * the returned array will contain two elements:
666
    * <pre>
667
    * array(
668
    *       "namespace" => "xslt",
669
    *       "localPart" => "stylesheet"
670
    *      );
671
    * </pre>
672
    *
673
    * @access public
674
    * @static
675
    * @param  string    $qname      qualified tag name
676
    * @param  string    $defaultNs  default namespace (optional)
677
    * @return array     $parts      array containing namespace and local part
678
    */
679
    function splitQualifiedName($qname, $defaultNs = null)
680
    {
681
        if (strstr($qname, ':')) {
682
            $tmp = explode(":", $qname);
683
            return array(
684
                          "namespace" => $tmp[0],
685
                          "localPart" => $tmp[1]
686
                        );
687
        }
688
        return array(
689
                      "namespace" => $defaultNs,
690
                      "localPart" => $qname
691
                    );
692
    }
693
 
694
   /**
695
    * check, whether string is valid XML name
696
    *
697
    * <p>XML names are used for tagname, attribute names and various
698
    * other, lesser known entities.</p>
699
    * <p>An XML name may only consist of alphanumeric characters,
700
    * dashes, undescores and periods, and has to start with a letter
701
    * or an underscore.
702
    * </p>
703
    *
704
    * <code>
705
    * require_once 'XML/Util.php';
706
    *
707
    * // verify tag name
708
    * $result = XML_Util::isValidName("invalidTag?");
709
    * if (XML_Util::isError($result)) {
710
    *    print "Invalid XML name: " . $result->getMessage();
711
    * }
712
    * </code>
713
    *
714
    * @access  public
715
    * @static
716
    * @param   string  $string string that should be checked
717
    * @return  mixed   $valid  true, if string is a valid XML name, PEAR error otherwise
718
    * @todo    support for other charsets
719
    */
720
    function isValidName($string)
721
    {
722
        // check for invalid chars
723
        if (!preg_match('/^[[:alpha:]_]$/', $string{0})) {
724
            return XML_Util::raiseError('XML names may only start with letter or underscore', XML_UTIL_ERROR_INVALID_START);
725
        }
726
 
727
        // check for invalid chars
728
        if (!preg_match('/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?[[:alpha:]_]([[:alnum:]\_\-\.]+)?$/', $string)) {
729
            return XML_Util::raiseError('XML names may only contain alphanumeric chars, period, hyphen, colon and underscores', XML_UTIL_ERROR_INVALID_CHARS);
730
         }
731
        // XML name is valid
732
        return true;
733
    }
734
 
735
   /**
736
    * replacement for XML_Util::raiseError
737
    *
738
    * Avoids the necessity to always require
739
    * PEAR.php
740
    *
741
    * @access   public
742
    * @param    string      error message
743
    * @param    integer     error code
744
    * @return   object PEAR_Error
745
    */
746
    function raiseError($msg, $code)
747
    {
748
        require_once 'PEAR.php';
749
        return PEAR::raiseError($msg, $code);
750
    }
751
}
752
?>