Source for file Util.php

Documentation is available at Util.php

  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 2006/07/12 17:57:59 ron Exp $
  20.  
  21.  
  22.  
  23. /**
  24. * error code for invalid chars in XML name
  25. */
  26. define("XML_UTIL_ERROR_INVALID_CHARS", 51);
  27.  
  28. /**
  29. * error code for invalid chars in XML name
  30. */
  31. define("XML_UTIL_ERROR_INVALID_START", 52);
  32.  
  33. /**
  34. * error code for non-scalar tag content
  35. */
  36. define("XML_UTIL_ERROR_NON_SCALAR_CONTENT", 60);
  37. /**
  38. * error code for missing tag name
  39. */
  40. define("XML_UTIL_ERROR_NO_TAG_NAME", 61);
  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. return sprintf("<?xml%s?>", XML_Util::attributesToString($attributes, false));
  227. }
  228.  
  229. /**
  230. * build a document type declaration
  231. *
  232. * <code>
  233. * require_once 'XML/Util.php';
  234. *
  235. * // get a doctype declaration:
  236. * $xmlDecl = XML_Util::getDocTypeDeclaration("rootTag","myDocType.dtd");
  237. * </code>
  238. *
  239. * @access public
  240. * @static
  241. * @param string $root name of the root tag
  242. * @param string $uri uri of the doctype definition (or array with uri and public id)
  243. * @param string $internalDtd internal dtd entries
  244. * @return string $decl doctype declaration
  245. * @since 0.2
  246. */
  247. function getDocTypeDeclaration($root, $uri = null, $internalDtd = null)
  248. {
  249. if (is_array($uri)) {
  250. $ref = sprintf( ' PUBLIC "%s" "%s"', $uri["id"], $uri["uri"] );
  251. } elseif (!empty($uri)) {
  252. $ref = sprintf( ' SYSTEM "%s"', $uri );
  253. } else {
  254. $ref = "";
  255. }
  256.  
  257. if (empty($internalDtd)) {
  258. return sprintf("<!DOCTYPE %s%s>", $root, $ref);
  259. } else {
  260. return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
  261. }
  262. }
  263.  
  264. /**
  265. * create string representation of an attribute list
  266. *
  267. * <code>
  268. * require_once 'XML/Util.php';
  269. *
  270. * // build an attribute string
  271. * $att = array(
  272. * "foo" => "bar",
  273. * "argh" => "tomato"
  274. * );
  275. *
  276. * $attList = XML_Util::attributesToString($att);
  277. * </code>
  278. *
  279. * @access public
  280. * @static
  281. * @param array $attributes attribute array
  282. * @param boolean|array$sort sort attribute list alphabetically, may also be an assoc array containing the keys 'sort', 'multiline', 'indent', 'linebreak' and 'entities'
  283. * @param boolean $multiline use linebreaks, if more than one attribute is given
  284. * @param string $indent string used for indentation of multiline attributes
  285. * @param string $linebreak string used for linebreaks of multiline attributes
  286. * @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)
  287. * @return string string representation of the attributes
  288. * @uses XML_Util::replaceEntities() to replace XML entities in attribute values
  289. * @todo allow sort also to be an options array
  290. */
  291. function attributesToString($attributes, $sort = true, $multiline = false, $indent = ' ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML)
  292. {
  293. /**
  294. * second parameter may be an array
  295. */
  296. if (is_array($sort)) {
  297. if (isset($sort['multiline'])) {
  298. $multiline = $sort['multiline'];
  299. }
  300. if (isset($sort['indent'])) {
  301. $indent = $sort['indent'];
  302. }
  303. if (isset($sort['linebreak'])) {
  304. $multiline = $sort['linebreak'];
  305. }
  306. if (isset($sort['entities'])) {
  307. $entities = $sort['entities'];
  308. }
  309. if (isset($sort['sort'])) {
  310. $sort = $sort['sort'];
  311. } else {
  312. $sort = true;
  313. }
  314. }
  315. $string = '';
  316. if (is_array($attributes) && !empty($attributes)) {
  317. if ($sort) {
  318. ksort($attributes);
  319. }
  320. if( !$multiline || count($attributes) == 1) {
  321. foreach ($attributes as $key => $value) {
  322. if ($entities != XML_UTIL_ENTITIES_NONE) {
  323. if ($entities === XML_UTIL_CDATA_SECTION) {
  324. $entities = XML_UTIL_ENTITIES_XML;
  325. }
  326. $value = XML_Util::replaceEntities($value, $entities);
  327. }
  328. $string .= ' '.$key.'="'.$value.'"';
  329. }
  330. } else {
  331. $first = true;
  332. foreach ($attributes as $key => $value) {
  333. if ($entities != XML_UTIL_ENTITIES_NONE) {
  334. $value = XML_Util::replaceEntities($value, $entities);
  335. }
  336. if ($first) {
  337. $string .= " ".$key.'="'.$value.'"';
  338. $first = false;
  339. } else {
  340. $string .= $linebreak.$indent.$key.'="'.$value.'"';
  341. }
  342. }
  343. }
  344. }
  345. return $string;
  346. }
  347.  
  348. /**
  349. * Collapses empty tags.
  350. *
  351. * @access public
  352. * @static
  353. * @param string $xml XML
  354. * @param integer $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL) or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
  355. * @return string $xml XML
  356. */
  357. function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL) {
  358. if ($mode == XML_UTIL_COLLAPSE_XHTML_ONLY) {
  359. return preg_replace(
  360. '/<(area|base|br|col|hr|img|input|link|meta|param)([^>]*)><\/\\1>/s',
  361. '<\\1\\2 />',
  362. $xml
  363. );
  364. } else {
  365. return preg_replace(
  366. '/<(\w+)([^>]*)><\/\\1>/s',
  367. '<\\1\\2 />',
  368. $xml
  369. );
  370. }
  371. }
  372.  
  373. /**
  374. * create a tag
  375. *
  376. * This method will call XML_Util::createTagFromArray(), which
  377. * is more flexible.
  378. *
  379. * <code>
  380. * require_once 'XML/Util.php';
  381. *
  382. * // create an XML tag:
  383. * $tag = XML_Util::createTag("myNs:myTag", array("foo" => "bar"), "This is inside the tag", "http://www.w3c.org/myNs#");
  384. * </code>
  385. *
  386. * @access public
  387. * @static
  388. * @param string $qname qualified tagname (including namespace)
  389. * @param array $attributes array containg attributes
  390. * @param mixed $content
  391. * @param string $namespaceUri URI of the namespace
  392. * @param integer $replaceEntities whether to replace XML special chars in content, embedd it in a CData section or none of both
  393. * @param boolean $multiline whether to create a multiline tag where each attribute gets written to a single line
  394. * @param string $indent string used to indent attributes (_auto indents attributes so they start at the same column)
  395. * @param string $linebreak string used for linebreaks
  396. * @return string $string XML tag
  397. * @see XML_Util::createTagFromArray()
  398. * @uses XML_Util::createTagFromArray() to create the tag
  399. */
  400. function createTag($qname, $attributes = array(), $content = null, $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n")
  401. {
  402. $tag = array(
  403. "qname" => $qname,
  404. "attributes" => $attributes
  405. );
  406.  
  407. // add tag content
  408. if ($content !== null) {
  409. $tag["content"] = $content;
  410. }
  411. // add namespace Uri
  412. if ($namespaceUri !== null) {
  413. $tag["namespaceUri"] = $namespaceUri;
  414. }
  415.  
  416. return XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $linebreak);
  417. }
  418.  
  419. /**
  420. * create a tag from an array
  421. * this method awaits an array in the following format
  422. * <pre>
  423. * array(
  424. * "qname" => $qname // qualified name of the tag
  425. * "namespace" => $namespace // namespace prefix (optional, if qname is specified or no namespace)
  426. * "localpart" => $localpart, // local part of the tagname (optional, if qname is specified)
  427. * "attributes" => array(), // array containing all attributes (optional)
  428. * "content" => $content, // tag content (optional)
  429. * "namespaceUri" => $namespaceUri // namespaceUri for the given namespace (optional)
  430. * )
  431. * </pre>
  432. *
  433. * <code>
  434. * require_once 'XML/Util.php';
  435. *
  436. * $tag = array(
  437. * "qname" => "foo:bar",
  438. * "namespaceUri" => "http://foo.com",
  439. * "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ),
  440. * "content" => "I'm inside the tag",
  441. * );
  442. * // creating a tag with qualified name and namespaceUri
  443. * $string = XML_Util::createTagFromArray($tag);
  444. * </code>
  445. *
  446. * @access public
  447. * @static
  448. * @param array $tag tag definition
  449. * @param integer $replaceEntities whether to replace XML special chars in content, embedd it in a CData section or none of both
  450. * @param boolean $multiline whether to create a multiline tag where each attribute gets written to a single line
  451. * @param string $indent string used to indent attributes (_auto indents attributes so they start at the same column)
  452. * @param string $linebreak string used for linebreaks
  453. * @return string $string XML tag
  454. * @see XML_Util::createTag()
  455. * @uses XML_Util::attributesToString() to serialize the attributes of the tag
  456. * @uses XML_Util::splitQualifiedName() to get local part and namespace of a qualified name
  457. */
  458. function createTagFromArray($tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n" )
  459. {
  460. if (isset($tag['content']) && !is_scalar($tag['content'])) {
  461. return XML_Util::raiseError( 'Supplied non-scalar value as tag content', XML_UTIL_ERROR_NON_SCALAR_CONTENT );
  462. }
  463.  
  464. if (!isset($tag['qname']) && !isset($tag['localPart'])) {
  465. return XML_Util::raiseError( 'You must either supply a qualified name (qname) or local tag name (localPart).', XML_UTIL_ERROR_NO_TAG_NAME );
  466. }
  467.  
  468. // if no attributes hav been set, use empty attributes
  469. if (!isset($tag["attributes"]) || !is_array($tag["attributes"])) {
  470. $tag["attributes"] = array();
  471. }
  472. // qualified name is not given
  473. if (!isset($tag["qname"])) {
  474. // check for namespace
  475. if (isset($tag["namespace"]) && !empty($tag["namespace"])) {
  476. $tag["qname"] = $tag["namespace"].":".$tag["localPart"];
  477. } else {
  478. $tag["qname"] = $tag["localPart"];
  479. }
  480. // namespace URI is set, but no namespace
  481. } elseif (isset($tag["namespaceUri"]) && !isset($tag["namespace"])) {
  482. $parts = XML_Util::splitQualifiedName($tag["qname"]);
  483. $tag["localPart"] = $parts["localPart"];
  484. if (isset($parts["namespace"])) {
  485. $tag["namespace"] = $parts["namespace"];
  486. }
  487. }
  488.  
  489. if (isset($tag["namespaceUri"]) && !empty($tag["namespaceUri"])) {
  490. // is a namespace given
  491. if (isset($tag["namespace"]) && !empty($tag["namespace"])) {
  492. $tag["attributes"]["xmlns:".$tag["namespace"]] = $tag["namespaceUri"];
  493. } else {
  494. // define this Uri as the default namespace
  495. $tag["attributes"]["xmlns"] = $tag["namespaceUri"];
  496. }
  497. }
  498.  
  499. // check for multiline attributes
  500. if ($multiline === true) {
  501. if ($indent === "_auto") {
  502. $indent = str_repeat(" ", (strlen($tag["qname"])+2));
  503. }
  504. }
  505. // create attribute list
  506. $attList = XML_Util::attributesToString($tag['attributes'], true, $multiline, $indent, $linebreak, $replaceEntities );
  507. if (!isset($tag['content']) || (string)$tag['content'] == '') {
  508. $tag = sprintf('<%s%s />', $tag['qname'], $attList);
  509. } else {
  510. switch ($replaceEntities) {
  511. case XML_UTIL_ENTITIES_NONE:
  512. break;
  513. case XML_UTIL_CDATA_SECTION:
  514. $tag['content'] = XML_Util::createCDataSection($tag['content']);
  515. break;
  516. default:
  517. $tag['content'] = XML_Util::replaceEntities($tag['content'], $replaceEntities);
  518. break;
  519. }
  520. $tag = sprintf('<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'], $tag['qname'] );
  521. }
  522. return $tag;
  523. }
  524.  
  525. /**
  526. * create a start element
  527. *
  528. * <code>
  529. * require_once 'XML/Util.php';
  530. *
  531. * // create an XML start element:
  532. * $tag = XML_Util::createStartElement("myNs:myTag", array("foo" => "bar") ,"http://www.w3c.org/myNs#");
  533. * </code>
  534. *
  535. * @access public
  536. * @static
  537. * @param string $qname qualified tagname (including namespace)
  538. * @param array $attributes array containg attributes
  539. * @param string $namespaceUri URI of the namespace
  540. * @param boolean $multiline whether to create a multiline tag where each attribute gets written to a single line
  541. * @param string $indent string used to indent attributes (_auto indents attributes so they start at the same column)
  542. * @param string $linebreak string used for linebreaks
  543. * @return string $string XML start element
  544. * @see XML_Util::createEndElement(), XML_Util::createTag()
  545. */
  546. function createStartElement($qname, $attributes = array(), $namespaceUri = null, $multiline = false, $indent = '_auto', $linebreak = "\n")
  547. {
  548. // if no attributes hav been set, use empty attributes
  549. if (!isset($attributes) || !is_array($attributes)) {
  550. $attributes = array();
  551. }
  552. if ($namespaceUri != null) {
  553. $parts = XML_Util::splitQualifiedName($qname);
  554. }
  555.  
  556. // check for multiline attributes
  557. if ($multiline === true) {
  558. if ($indent === "_auto") {
  559. $indent = str_repeat(" ", (strlen($qname)+2));
  560. }
  561. }
  562.  
  563. if ($namespaceUri != null) {
  564. // is a namespace given
  565. if (isset($parts["namespace"]) && !empty($parts["namespace"])) {
  566. $attributes["xmlns:".$parts["namespace"]] = $namespaceUri;
  567. } else {
  568. // define this Uri as the default namespace
  569. $attributes["xmlns"] = $namespaceUri;
  570. }
  571. }
  572.  
  573. // create attribute list
  574. $attList = XML_Util::attributesToString($attributes, true, $multiline, $indent, $linebreak);
  575. $element = sprintf("<%s%s>", $qname, $attList);
  576. return $element;
  577. }
  578.  
  579. /**
  580. * create an end element
  581. *
  582. * <code>
  583. * require_once 'XML/Util.php';
  584. *
  585. * // create an XML start element:
  586. * $tag = XML_Util::createEndElement("myNs:myTag");
  587. * </code>
  588. *
  589. * @access public
  590. * @static
  591. * @param string $qname qualified tagname (including namespace)
  592. * @return string $string XML end element
  593. * @see XML_Util::createStartElement(), XML_Util::createTag()
  594. */
  595. function createEndElement($qname)
  596. {
  597. $element = sprintf("</%s>", $qname);
  598. return $element;
  599. }
  600. /**
  601. * create an XML comment
  602. *
  603. * <code>
  604. * require_once 'XML/Util.php';
  605. *
  606. * // create an XML start element:
  607. * $tag = XML_Util::createComment("I am a comment");
  608. * </code>
  609. *
  610. * @access public
  611. * @static
  612. * @param string $content content of the comment
  613. * @return string $comment XML comment
  614. */
  615. function createComment($content)
  616. {
  617. $comment = sprintf("<!-- %s -->", $content);
  618. return $comment;
  619. }
  620. /**
  621. * create a CData section
  622. *
  623. * <code>
  624. * require_once 'XML/Util.php';
  625. *
  626. * // create a CData section
  627. * $tag = XML_Util::createCDataSection("I am content.");
  628. * </code>
  629. *
  630. * @access public
  631. * @static
  632. * @param string $data data of the CData section
  633. * @return string $string CData section with content
  634. */
  635. function createCDataSection($data)
  636. {
  637. return sprintf("<![CDATA[%s]]>", $data);
  638. }
  639.  
  640. /**
  641. * split qualified name and return namespace and local part
  642. *
  643. * <code>
  644. * require_once 'XML/Util.php';
  645. *
  646. * // split qualified tag
  647. * $parts = XML_Util::splitQualifiedName("xslt:stylesheet");
  648. * </code>
  649. * the returned array will contain two elements:
  650. * <pre>
  651. * array(
  652. * "namespace" => "xslt",
  653. * "localPart" => "stylesheet"
  654. * );
  655. * </pre>
  656. *
  657. * @access public
  658. * @static
  659. * @param string $qname qualified tag name
  660. * @param string $defaultNs default namespace (optional)
  661. * @return array $parts array containing namespace and local part
  662. */
  663. function splitQualifiedName($qname, $defaultNs = null)
  664. {
  665. if (strstr($qname, ':')) {
  666. $tmp = explode(":", $qname);
  667. return array(
  668. "namespace" => $tmp[0],
  669. "localPart" => $tmp[1]
  670. );
  671. }
  672. return array(
  673. "namespace" => $defaultNs,
  674. "localPart" => $qname
  675. );
  676. }
  677.  
  678. /**
  679. * check, whether string is valid XML name
  680. *
  681. * <p>XML names are used for tagname, attribute names and various
  682. * other, lesser known entities.</p>
  683. * <p>An XML name may only consist of alphanumeric characters,
  684. * dashes, undescores and periods, and has to start with a letter
  685. * or an underscore.
  686. * </p>
  687. *
  688. * <code>
  689. * require_once 'XML/Util.php';
  690. *
  691. * // verify tag name
  692. * $result = XML_Util::isValidName("invalidTag?");
  693. * if (XML_Util::isError($result)) {
  694. * print "Invalid XML name: " . $result->getMessage();
  695. * }
  696. * </code>
  697. *
  698. * @access public
  699. * @static
  700. * @param string $string string that should be checked
  701. * @return mixed $valid true, if string is a valid XML name, PEAR error otherwise
  702. * @todo support for other charsets
  703. */
  704. function isValidName($string)
  705. {
  706. // check for invalid chars
  707. if (!preg_match("/^[[:alnum:]_\-.]$/", $string{0})) {
  708. return XML_Util::raiseError( "XML names may only start with letter or underscore", XML_UTIL_ERROR_INVALID_START );
  709. }
  710. // check for invalid chars
  711. if (!preg_match("/^([a-zA-Z_]([a-zA-Z0-9_\-\.]*)?:)?[a-zA-Z_]([a-zA-Z0-9_\-\.]+)?$/", $string)) {
  712. return XML_Util::raiseError( "XML names may only contain alphanumeric chars, period, hyphen, colon and underscores", XML_UTIL_ERROR_INVALID_CHARS );
  713. }
  714. // XML name is valid
  715. return true;
  716. }
  717.  
  718. /**
  719. * replacement for XML_Util::raiseError
  720. *
  721. * Avoids the necessity to always require
  722. * PEAR.php
  723. *
  724. * @access public
  725. * @param string error message
  726. * @param integer error code
  727. * @return object PEAR_Error
  728. */
  729. function raiseError($msg, $code)
  730. {
  731. require_once 'PEAR.php';
  732. return PEAR::raiseError($msg, $code);
  733. }
  734. }
  735. ?>

Documentation generated on Mon, 04 Dec 2006 11:10:20 -0500 by phpDocumentor 1.3.0RC3