home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / XML / Util.php < prev    next >
Encoding:
PHP Script  |  2008-07-02  |  27.2 KB  |  752 lines

  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.  */
  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.                                           '&'  => '&',
  132.                                           '>'  => '>',
  133.                                           '<'  => '<',
  134.                                           '"'  => '"',
  135.                                           '\'' => ''' ));
  136.                 break;
  137.             case XML_UTIL_ENTITIES_XML_REQUIRED:
  138.                 return strtr($string,array(
  139.                                           '&'  => '&',
  140.                                           '<'  => '<',
  141.                                           '"'  => '"' ));
  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 < & >.");
  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.                                           '&'  => '&',
  176.                                           '>'   => '>',
  177.                                           '<'   => '<',
  178.                                           '"' => '"',
  179.                                           ''' => '\'' ));
  180.                 break;
  181.             case XML_UTIL_ENTITIES_XML_REQUIRED:
  182.                 return strtr($string,array(
  183.                                           '&'  => '&',
  184.                                           '<'   => '<',
  185.                                           '"' => '"' ));
  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. ?>