ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
Util.php
Go to the documentation of this file.
1 <?php
2 
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4 
53 define('XML_UTIL_ERROR_INVALID_CHARS', 51);
54 
58 define('XML_UTIL_ERROR_INVALID_START', 52);
59 
63 define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);
64 
68 define('XML_UTIL_ERROR_NO_TAG_NAME', 61);
69 
73 define('XML_UTIL_REPLACE_ENTITIES', 1);
74 
78 define('XML_UTIL_CDATA_SECTION', 5);
79 
83 define('XML_UTIL_ENTITIES_NONE', 0);
84 
89 define('XML_UTIL_ENTITIES_XML', 1);
90 
95 define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);
96 
101 define('XML_UTIL_ENTITIES_HTML', 3);
102 
106 define('XML_UTIL_COLLAPSE_ALL', 1);
107 
111 define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);
112 
125 class XML_Util
126 {
134  function apiVersion()
135  {
136  return '1.1';
137  }
138 
179  function replaceEntities($string, $replaceEntities = XML_UTIL_ENTITIES_XML,
180  $encoding = 'ISO-8859-1')
181  {
182  switch ($replaceEntities) {
184  return strtr($string, array(
185  '&' => '&amp;',
186  '>' => '&gt;',
187  '<' => '&lt;',
188  '"' => '&quot;',
189  '\'' => '&apos;' ));
190  break;
192  return strtr($string, array(
193  '&' => '&amp;',
194  '<' => '&lt;',
195  '"' => '&quot;' ));
196  break;
198  return htmlentities($string, ENT_COMPAT, $encoding);
199  break;
200  }
201  return $string;
202  }
203 
245  function reverseEntities($string, $replaceEntities = XML_UTIL_ENTITIES_XML,
246  $encoding = 'ISO-8859-1')
247  {
248  switch ($replaceEntities) {
250  return strtr($string, array(
251  '&amp;' => '&',
252  '&gt;' => '>',
253  '&lt;' => '<',
254  '&quot;' => '"',
255  '&apos;' => '\'' ));
256  break;
258  return strtr($string, array(
259  '&amp;' => '&',
260  '&lt;' => '<',
261  '&quot;' => '"' ));
262  break;
264  return html_entity_decode($string, ENT_COMPAT, $encoding);
265  break;
266  }
267  return $string;
268  }
269 
289  function getXMLDeclaration($version = '1.0', $encoding = null,
290  $standalone = null)
291  {
292  $attributes = array(
293  'version' => $version,
294  );
295  // add encoding
296  if ($encoding !== null) {
297  $attributes['encoding'] = $encoding;
298  }
299  // add standalone, if specified
300  if ($standalone !== null) {
301  $attributes['standalone'] = $standalone ? 'yes' : 'no';
302  }
303 
304  return sprintf('<?xml%s?>',
305  XML_Util::attributesToString($attributes, false));
306  }
307 
328  function getDocTypeDeclaration($root, $uri = null, $internalDtd = null)
329  {
330  if (is_array($uri)) {
331  $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
332  } elseif (!empty($uri)) {
333  $ref = sprintf(' SYSTEM "%s"', $uri);
334  } else {
335  $ref = '';
336  }
337 
338  if (empty($internalDtd)) {
339  return sprintf('<!DOCTYPE %s%s>', $root, $ref);
340  } else {
341  return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
342  }
343  }
344 
383  function attributesToString($attributes, $sort = true, $multiline = false,
384  $indent = ' ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML)
385  {
386  /*
387  * second parameter may be an array
388  */
389  if (is_array($sort)) {
390  if (isset($sort['multiline'])) {
391  $multiline = $sort['multiline'];
392  }
393  if (isset($sort['indent'])) {
394  $indent = $sort['indent'];
395  }
396  if (isset($sort['linebreak'])) {
397  $multiline = $sort['linebreak'];
398  }
399  if (isset($sort['entities'])) {
400  $entities = $sort['entities'];
401  }
402  if (isset($sort['sort'])) {
403  $sort = $sort['sort'];
404  } else {
405  $sort = true;
406  }
407  }
408  $string = '';
409  if (is_array($attributes) && !empty($attributes)) {
410  if ($sort) {
411  ksort($attributes);
412  }
413  if ( !$multiline || count($attributes) == 1) {
414  foreach ($attributes as $key => $value) {
415  if ($entities != XML_UTIL_ENTITIES_NONE) {
416  if ($entities === XML_UTIL_CDATA_SECTION) {
417  $entities = XML_UTIL_ENTITIES_XML;
418  }
419  $value = XML_Util::replaceEntities($value, $entities);
420  }
421  $string .= ' ' . $key . '="' . $value . '"';
422  }
423  } else {
424  $first = true;
425  foreach ($attributes as $key => $value) {
426  if ($entities != XML_UTIL_ENTITIES_NONE) {
427  $value = XML_Util::replaceEntities($value, $entities);
428  }
429  if ($first) {
430  $string .= ' ' . $key . '="' . $value . '"';
431  $first = false;
432  } else {
433  $string .= $linebreak . $indent . $key . '="' . $value . '"';
434  }
435  }
436  }
437  }
438  return $string;
439  }
440 
454  function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
455  {
456  if ($mode == XML_UTIL_COLLAPSE_XHTML_ONLY) {
457  return preg_replace(
458  '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
459  . 'param)([^>]*)><\/\\1>/s',
460  '<\\1\\2 />',
461  $xml);
462  } else {
463  return preg_replace('/<(\w+)([^>]*)><\/\\1>/s', '<\\1\\2 />', $xml);
464  }
465  }
466 
504  function createTag($qname, $attributes = array(), $content = null,
505  $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
506  $multiline = false, $indent = '_auto', $linebreak = "\n",
507  $sortAttributes = true)
508  {
509  $tag = array(
510  'qname' => $qname,
511  'attributes' => $attributes
512  );
513 
514  // add tag content
515  if ($content !== null) {
516  $tag['content'] = $content;
517  }
518 
519  // add namespace Uri
520  if ($namespaceUri !== null) {
521  $tag['namespaceUri'] = $namespaceUri;
522  }
523 
524  return XML_Util::createTagFromArray($tag, $replaceEntities, $multiline,
525  $indent, $linebreak, $sortAttributes);
526  }
527 
587  function createTagFromArray($tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
588  $multiline = false, $indent = '_auto', $linebreak = "\n",
589  $sortAttributes = true)
590  {
591  if (isset($tag['content']) && !is_scalar($tag['content'])) {
592  return XML_Util::raiseError('Supplied non-scalar value as tag content',
594  }
595 
596  if (!isset($tag['qname']) && !isset($tag['localPart'])) {
597  return XML_Util::raiseError('You must either supply a qualified name '
598  . '(qname) or local tag name (localPart).',
600  }
601 
602  // if no attributes hav been set, use empty attributes
603  if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
604  $tag['attributes'] = array();
605  }
606 
607  if (isset($tag['namespaces'])) {
608  foreach ($tag['namespaces'] as $ns => $uri) {
609  $tag['attributes']['xmlns:' . $ns] = $uri;
610  }
611  }
612 
613  if (!isset($tag['qname'])) {
614  // qualified name is not given
615 
616  // check for namespace
617  if (isset($tag['namespace']) && !empty($tag['namespace'])) {
618  $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
619  } else {
620  $tag['qname'] = $tag['localPart'];
621  }
622  } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
623  // namespace URI is set, but no namespace
624 
625  $parts = XML_Util::splitQualifiedName($tag['qname']);
626 
627  $tag['localPart'] = $parts['localPart'];
628  if (isset($parts['namespace'])) {
629  $tag['namespace'] = $parts['namespace'];
630  }
631  }
632 
633  if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
634  // is a namespace given
635  if (isset($tag['namespace']) && !empty($tag['namespace'])) {
636  $tag['attributes']['xmlns:' . $tag['namespace']] =
637  $tag['namespaceUri'];
638  } else {
639  // define this Uri as the default namespace
640  $tag['attributes']['xmlns'] = $tag['namespaceUri'];
641  }
642  }
643 
644  // check for multiline attributes
645  if ($multiline === true) {
646  if ($indent === '_auto') {
647  $indent = str_repeat(' ', (strlen($tag['qname'])+2));
648  }
649  }
650 
651  // create attribute list
652  $attList = XML_Util::attributesToString($tag['attributes'],
653  $sortAttributes, $multiline, $indent, $linebreak, $replaceEntities);
654  if (!isset($tag['content']) || (string)$tag['content'] == '') {
655  $tag = sprintf('<%s%s />', $tag['qname'], $attList);
656  } else {
657  switch ($replaceEntities) {
659  break;
661  $tag['content'] = XML_Util::createCDataSection($tag['content']);
662  break;
663  default:
664  $tag['content'] = XML_Util::replaceEntities($tag['content'],
665  $replaceEntities);
666  break;
667  }
668  $tag = sprintf('<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
669  $tag['qname']);
670  }
671  return $tag;
672  }
673 
700  function createStartElement($qname, $attributes = array(), $namespaceUri = null,
701  $multiline = false, $indent = '_auto', $linebreak = "\n",
702  $sortAttributes = true)
703  {
704  // if no attributes hav been set, use empty attributes
705  if (!isset($attributes) || !is_array($attributes)) {
706  $attributes = array();
707  }
708 
709  if ($namespaceUri != null) {
710  $parts = XML_Util::splitQualifiedName($qname);
711  }
712 
713  // check for multiline attributes
714  if ($multiline === true) {
715  if ($indent === '_auto') {
716  $indent = str_repeat(' ', (strlen($qname)+2));
717  }
718  }
719 
720  if ($namespaceUri != null) {
721  // is a namespace given
722  if (isset($parts['namespace']) && !empty($parts['namespace'])) {
723  $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
724  } else {
725  // define this Uri as the default namespace
726  $attributes['xmlns'] = $namespaceUri;
727  }
728  }
729 
730  // create attribute list
731  $attList = XML_Util::attributesToString($attributes, $sortAttributes,
732  $multiline, $indent, $linebreak);
733  $element = sprintf('<%s%s>', $qname, $attList);
734  return $element;
735  }
736 
754  function createEndElement($qname)
755  {
756  $element = sprintf('</%s>', $qname);
757  return $element;
758  }
759 
776  function createComment($content)
777  {
778  $comment = sprintf('<!-- %s -->', $content);
779  return $comment;
780  }
781 
799  {
800  return sprintf('<![CDATA[%s]]>',
801  preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data)));
802 
803  }
804 
829  function splitQualifiedName($qname, $defaultNs = null)
830  {
831  if (strstr($qname, ':')) {
832  $tmp = explode(':', $qname);
833  return array(
834  'namespace' => $tmp[0],
835  'localPart' => $tmp[1]
836  );
837  }
838  return array(
839  'namespace' => $defaultNs,
840  'localPart' => $qname
841  );
842  }
843 
871  function isValidName($string)
872  {
873  // check for invalid chars
874  if (!preg_match('/^[[:alpha:]_]$/', $string{0})) {
875  return XML_Util::raiseError('XML names may only start with letter '
876  . 'or underscore', XML_UTIL_ERROR_INVALID_START);
877  }
878 
879  // check for invalid chars
880  if (!preg_match('/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?[[:alpha:]_]([[:alnum:]\_\-\.]+)?$/',
881  $string)
882  ) {
883  return XML_Util::raiseError('XML names may only contain alphanumeric '
884  . 'chars, period, hyphen, colon and underscores',
886  }
887  // XML name is valid
888  return true;
889  }
890 
905  function raiseError($msg, $code)
906  {
907  require_once 'PEAR.php';
908  return PEAR::raiseError($msg, $code);
909  }
910 }
911 ?>