PageRenderTime 485ms CodeModel.GetById 131ms app.highlight 73ms RepoModel.GetById 142ms app.codeStats 0ms

/public/javascripts/jquery/tools/juice/lib/php/PEAR/XML_Util/Util.php

https://github.com/mikeymicrophone/basicblog
PHP | 752 lines | 303 code | 46 blank | 403 comment | 73 complexity | d8da94df3701e71249825a1ac8aa3635 MD5 | raw file
  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.28 2006/12/16 09:42:56 schst Exp $
 20
 21/**
 22 * error code for invalid chars in XML name
 23 */
 24define("XML_UTIL_ERROR_INVALID_CHARS", 51);
 25
 26/**
 27 * error code for invalid chars in XML name
 28 */
 29define("XML_UTIL_ERROR_INVALID_START", 52);
 30
 31/**
 32 * error code for non-scalar tag content
 33 */
 34define("XML_UTIL_ERROR_NON_SCALAR_CONTENT", 60);
 35
 36/**
 37 * error code for missing tag name
 38 */
 39define("XML_UTIL_ERROR_NO_TAG_NAME", 61);
 40
 41/**
 42 * replace XML entities
 43 */
 44define("XML_UTIL_REPLACE_ENTITIES", 1);
 45
 46/**
 47 * embedd content in a CData Section
 48 */
 49define("XML_UTIL_CDATA_SECTION", 5);
 50
 51/**
 52 * do not replace entitites
 53 */
 54define("XML_UTIL_ENTITIES_NONE", 0);
 55
 56/**
 57 * replace all XML entitites
 58 * This setting will replace <, >, ", ' and &
 59 */
 60define("XML_UTIL_ENTITIES_XML", 1);
 61
 62/**
 63 * replace only required XML entitites
 64 * This setting will replace <, " and &
 65 */
 66define("XML_UTIL_ENTITIES_XML_REQUIRED", 2);
 67
 68/**
 69 * replace HTML entitites
 70 * @link    http://www.php.net/htmlentities
 71 */
 72define("XML_UTIL_ENTITIES_HTML", 3);
 73
 74/**
 75 * Collapse all empty tags.
 76 */
 77define("XML_UTIL_COLLAPSE_ALL", 1);
 78
 79/**
 80 * Collapse only empty XHTML tags that have no end tag.
 81 */
 82define("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 */
 92class 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?>