PageRenderTime 35ms CodeModel.GetById 7ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

/app/libs/PEAR/XML/Util.php

https://github.com/aborruso/geocloud2
PHP | 743 lines | 298 code | 45 blank | 400 comment | 72 complexity | 7d23b2001adad770c3b76f72b25ff48a 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.1 2009/03/26 18:56:30 mhoegh 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    * @return   string  $string            XML tag

398    * @see      XML_Util::createTagFromArray()

399    * @uses     XML_Util::createTagFromArray() to create the tag

400    */

401    function createTag($qname, $attributes = array(), $content = null, $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n")

402    {

403        $tag = array(

404                     "qname"      => $qname,

405                     "attributes" => $attributes

406                    );

407

408        // add tag content

409        if ($content !== null) {

410            $tag["content"] = $content;

411        }

412        

413        // add namespace Uri

414        if ($namespaceUri !== null) {

415            $tag["namespaceUri"] = $namespaceUri;

416        }

417

418        return XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $linebreak);

419    }

420

421   /**

422    * create a tag from an array

423    * this method awaits an array in the following format

424    * <pre>

425    * array(

426    *  "qname"        => $qname         // qualified name of the tag

427    *  "namespace"    => $namespace     // namespace prefix (optional, if qname is specified or no namespace)

428    *  "localpart"    => $localpart,    // local part of the tagname (optional, if qname is specified)

429    *  "attributes"   => array(),       // array containing all attributes (optional)

430    *  "content"      => $content,      // tag content (optional)

431    *  "namespaceUri" => $namespaceUri  // namespaceUri for the given namespace (optional)

432    *   )

433    * </pre>

434    *

435    * <code>

436    * require_once 'XML/Util.php';

437    * 

438    * $tag = array(

439    *           "qname"        => "foo:bar",

440    *           "namespaceUri" => "http://foo.com",

441    *           "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),

442    *           "content"      => "I'm inside the tag",

443    *            );

444    * // creating a tag with qualified name and namespaceUri

445    * $string = XML_Util::createTagFromArray($tag);

446    * </code>

447    *

448    * @access   public

449    * @static

450    * @param    array   $tag               tag definition

451    * @param    integer $replaceEntities   whether to replace XML special chars in content, embedd it in a CData section or none of both

452    * @param    boolean $multiline         whether to create a multiline tag where each attribute gets written to a single line

453    * @param    string  $indent            string used to indent attributes (_auto indents attributes so they start at the same column)

454    * @param    string  $linebreak         string used for linebreaks

455    * @return   string  $string            XML tag

456    * @see      XML_Util::createTag()

457    * @uses     XML_Util::attributesToString() to serialize the attributes of the tag

458    * @uses     XML_Util::splitQualifiedName() to get local part and namespace of a qualified name

459    */

460    function createTagFromArray($tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n" )

461    {

462        if (isset($tag['content']) && !is_scalar($tag['content'])) {

463            return XML_Util::raiseError( 'Supplied non-scalar value as tag content', XML_UTIL_ERROR_NON_SCALAR_CONTENT );

464        }

465

466        if (!isset($tag['qname']) && !isset($tag['localPart'])) {

467            return XML_Util::raiseError( 'You must either supply a qualified name (qname) or local tag name (localPart).', XML_UTIL_ERROR_NO_TAG_NAME );

468        }

469

470        // if no attributes hav been set, use empty attributes

471        if (!isset($tag["attributes"]) || !is_array($tag["attributes"])) {

472            $tag["attributes"] = array();

473        }

474        

475        // qualified name is not given

476        if (!isset($tag["qname"])) {

477            // check for namespace

478            if (isset($tag["namespace"]) && !empty($tag["namespace"])) {

479                $tag["qname"] = $tag["namespace"].":".$tag["localPart"];

480            } else {

481                $tag["qname"] = $tag["localPart"];

482            }

483        // namespace URI is set, but no namespace

484        } elseif (isset($tag["namespaceUri"]) && !isset($tag["namespace"])) {

485            $parts = XML_Util::splitQualifiedName($tag["qname"]);

486            $tag["localPart"] = $parts["localPart"];

487            if (isset($parts["namespace"])) {

488                $tag["namespace"] = $parts["namespace"];

489            }

490        }

491

492        if (isset($tag["namespaceUri"]) && !empty($tag["namespaceUri"])) {

493            // is a namespace given

494            if (isset($tag["namespace"]) && !empty($tag["namespace"])) {

495                $tag["attributes"]["xmlns:".$tag["namespace"]] = $tag["namespaceUri"];

496            } else {

497                // define this Uri as the default namespace

498                $tag["attributes"]["xmlns"] = $tag["namespaceUri"];

499            }

500        }

501

502        // check for multiline attributes

503        if ($multiline === true) {

504            if ($indent === "_auto") {

505                $indent = str_repeat(" ", (strlen($tag["qname"])+2));

506            }

507        }

508        

509        // create attribute list

510        $attList    =   XML_Util::attributesToString($tag['attributes'], true, $multiline, $indent, $linebreak, $replaceEntities );

511        if (!isset($tag['content']) || (string)$tag['content'] == '') {

512            $tag    =   sprintf('<%s%s />', $tag['qname'], $attList);

513        } else {

514            switch ($replaceEntities) {

515                case XML_UTIL_ENTITIES_NONE:

516                    break;

517                case XML_UTIL_CDATA_SECTION:

518                    $tag['content'] = XML_Util::createCDataSection($tag['content']);

519                    break;

520                default:

521                    $tag['content'] = XML_Util::replaceEntities($tag['content'], $replaceEntities);

522                    break;

523            }

524            $tag    =   sprintf('<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'], $tag['qname'] );

525        }        

526        return  $tag;

527    }

528

529   /**

530    * create a start element

531    *

532    * <code>

533    * require_once 'XML/Util.php';

534    * 

535    * // create an XML start element:

536    * $tag = XML_Util::createStartElement("myNs:myTag", array("foo" => "bar") ,"http://www.w3c.org/myNs#");

537    * </code>

538    *

539    * @access   public

540    * @static

541    * @param    string  $qname             qualified tagname (including namespace)

542    * @param    array   $attributes        array containg attributes

543    * @param    string  $namespaceUri      URI of the namespace

544    * @param    boolean $multiline         whether to create a multiline tag where each attribute gets written to a single line

545    * @param    string  $indent            string used to indent attributes (_auto indents attributes so they start at the same column)

546    * @param    string  $linebreak         string used for linebreaks

547    * @return   string  $string            XML start element

548    * @see      XML_Util::createEndElement(), XML_Util::createTag()

549    */

550    function createStartElement($qname, $attributes = array(), $namespaceUri = null, $multiline = false, $indent = '_auto', $linebreak = "\n")

551    {

552        // if no attributes hav been set, use empty attributes

553        if (!isset($attributes) || !is_array($attributes)) {

554            $attributes = array();

555        }

556        

557        if ($namespaceUri != null) {

558            $parts = XML_Util::splitQualifiedName($qname);

559        }

560

561        // check for multiline attributes

562        if ($multiline === true) {

563            if ($indent === "_auto") {

564                $indent = str_repeat(" ", (strlen($qname)+2));

565            }

566        }

567

568        if ($namespaceUri != null) {

569            // is a namespace given

570            if (isset($parts["namespace"]) && !empty($parts["namespace"])) {

571                $attributes["xmlns:".$parts["namespace"]] = $namespaceUri;

572            } else {

573                // define this Uri as the default namespace

574                $attributes["xmlns"] = $namespaceUri;

575            }

576        }

577

578        // create attribute list

579        $attList    =   XML_Util::attributesToString($attributes, true, $multiline, $indent, $linebreak);

580        $element    =   sprintf("<%s%s>", $qname, $attList);

581        return  $element;

582    }

583

584   /**

585    * create an end element

586    *

587    * <code>

588    * require_once 'XML/Util.php';

589    * 

590    * // create an XML start element:

591    * $tag = XML_Util::createEndElement("myNs:myTag");

592    * </code>

593    *

594    * @access   public

595    * @static

596    * @param    string  $qname             qualified tagname (including namespace)

597    * @return   string  $string            XML end element

598    * @see      XML_Util::createStartElement(), XML_Util::createTag()

599    */

600    function createEndElement($qname)

601    {

602        $element    =   sprintf("</%s>", $qname);

603        return  $element;

604    }

605    

606   /**

607    * create an XML comment

608    *

609    * <code>

610    * require_once 'XML/Util.php';

611    * 

612    * // create an XML start element:

613    * $tag = XML_Util::createComment("I am a comment");

614    * </code>

615    *

616    * @access   public

617    * @static

618    * @param    string  $content           content of the comment

619    * @return   string  $comment           XML comment

620    */

621    function createComment($content)

622    {

623        $comment    =   sprintf("<!-- %s -->", $content);

624        return  $comment;

625    }

626    

627   /**

628    * create a CData section

629    *

630    * <code>

631    * require_once 'XML/Util.php';

632    * 

633    * // create a CData section

634    * $tag = XML_Util::createCDataSection("I am content.");

635    * </code>

636    *

637    * @access   public

638    * @static

639    * @param    string  $data              data of the CData section

640    * @return   string  $string            CData section with content

641    */

642    function createCDataSection($data)

643    {

644        return  sprintf("<![CDATA[%s]]>", $data);

645    }

646

647   /**

648    * split qualified name and return namespace and local part

649    *

650    * <code>

651    * require_once 'XML/Util.php';

652    * 

653    * // split qualified tag

654    * $parts = XML_Util::splitQualifiedName("xslt:stylesheet");

655    * </code>

656    * the returned array will contain two elements:

657    * <pre>

658    * array(

659    *       "namespace" => "xslt",

660    *       "localPart" => "stylesheet"

661    *      );

662    * </pre>

663    *

664    * @access public

665    * @static

666    * @param  string    $qname      qualified tag name

667    * @param  string    $defaultNs  default namespace (optional)

668    * @return array     $parts      array containing namespace and local part

669    */

670    function splitQualifiedName($qname, $defaultNs = null)

671    {

672        if (strstr($qname, ':')) {

673            $tmp = explode(":", $qname);

674            return array(

675                          "namespace" => $tmp[0],

676                          "localPart" => $tmp[1]

677                        );

678        }

679        return array(

680                      "namespace" => $defaultNs,

681                      "localPart" => $qname

682                    );

683    }

684

685   /**

686    * check, whether string is valid XML name

687    *

688    * <p>XML names are used for tagname, attribute names and various

689    * other, lesser known entities.</p>

690    * <p>An XML name may only consist of alphanumeric characters,

691    * dashes, undescores and periods, and has to start with a letter

692    * or an underscore.

693    * </p>

694    *

695    * <code>

696    * require_once 'XML/Util.php';

697    * 

698    * // verify tag name

699    * $result = XML_Util::isValidName("invalidTag?");

700    * if (XML_Util::isError($result)) {

701    *    print "Invalid XML name: " . $result->getMessage();

702    * }

703    * </code>

704    *

705    * @access  public

706    * @static

707    * @param   string  $string string that should be checked

708    * @return  mixed   $valid  true, if string is a valid XML name, PEAR error otherwise

709    * @todo    support for other charsets

710    */

711    function isValidName($string)

712    {

713        // check for invalid chars

714        if (!preg_match("/^[[:alnum:]_\-.]$/", $string{0})) {

715            return XML_Util::raiseError( "XML names may only start with letter or underscore", XML_UTIL_ERROR_INVALID_START );

716        }

717        

718        // check for invalid chars

719        if (!preg_match("/^([a-zA-Z_]([a-zA-Z0-9_\-\.]*)?:)?[a-zA-Z_]([a-zA-Z0-9_\-\.]+)?$/", $string)) {

720            return XML_Util::raiseError( "XML names may only contain alphanumeric chars, period, hyphen, colon and underscores", XML_UTIL_ERROR_INVALID_CHARS );

721         }

722        // XML name is valid

723        return true;

724    }

725

726   /**

727    * replacement for XML_Util::raiseError

728    *

729    * Avoids the necessity to always require

730    * PEAR.php

731    *

732    * @access   public

733    * @param    string      error message

734    * @param    integer     error code

735    * @return   object PEAR_Error

736    */

737    function raiseError($msg, $code)

738    {

739        require_once 'PEAR.php';

740        return PEAR::raiseError($msg, $code);

741    }

742}

743?>