Overview

Namespaces

  • Contrib
    • Bundle
      • CoverallsBundle
        • Console
        • Entity
      • CoverallsV1Bundle
        • Api
        • Collector
        • Command
        • Config
        • Entity
          • Git
    • Component
      • File
      • Log
      • System
        • Git
  • Guzzle
    • Batch
      • Exception
    • Cache
    • Common
      • Exception
    • Http
      • Curl
      • Exception
      • Message
      • QueryAggregator
    • Inflection
    • Iterator
    • Log
    • Parser
      • Cookie
      • Message
      • UriTemplate
      • Url
    • Plugin
      • Async
      • Backoff
      • Cache
      • Cookie
        • CookieJar
        • Exception
      • CurlAuth
      • ErrorResponse
        • Exception
      • History
      • Log
      • Md5
      • Mock
      • Oauth
    • Service
      • Builder
      • Command
        • Factory
        • LocationVisitor
          • Request
          • Response
      • Description
      • Exception
      • Resource
    • Stream
  • PHP
  • Psr
    • Log
  • Symfony
    • Component
      • Config
        • Definition
          • Builder
          • Exception
        • Exception
        • Loader
        • Resource
        • Util
      • Console
        • Command
        • Formatter
        • Helper
        • Input
        • Output
        • Tester
      • EventDispatcher
        • Debug
      • Finder
        • Adapter
        • Comparator
        • Exception
        • Expression
        • Iterator
        • Shell
      • Stopwatch
      • Yaml
        • Exception

Classes

  • XmlUtils
  • Overview
  • Namespace
  • Class
  • Tree
  • Todo
  1: <?php
  2: 
  3: /*
  4:  * This file is part of the Symfony package.
  5:  *
  6:  * (c) Fabien Potencier <fabien@symfony.com>
  7:  *
  8:  * For the full copyright and license information, please view the LICENSE
  9:  * file that was distributed with this source code.
 10:  */
 11: 
 12: namespace Symfony\Component\Config\Util;
 13: 
 14: /**
 15:  * XMLUtils is a bunch of utility methods to XML operations.
 16:  *
 17:  * This class contains static methods only and is not meant to be instantiated.
 18:  *
 19:  * @author Fabien Potencier <fabien@symfony.com>
 20:  * @author Martin HasoĊˆ <martin.hason@gmail.com>
 21:  */
 22: class XmlUtils
 23: {
 24:     /**
 25:      * This class should not be instantiated
 26:      */
 27:     private function __construct()
 28:     {
 29:     }
 30: 
 31:     /**
 32:      * Loads an XML file.
 33:      *
 34:      * @param string $file                      An XML file path
 35:      * @param string|callable $schemaOrCallable An XSD schema file path or callable
 36:      *
 37:      * @return \DOMDocument
 38:      *
 39:      * @throws \InvalidArgumentException When loading of XML file returns error
 40:      */
 41:     public static function loadFile($file, $schemaOrCallable = null)
 42:     {
 43:         $internalErrors = libxml_use_internal_errors(true);
 44:         $disableEntities = libxml_disable_entity_loader(true);
 45:         libxml_clear_errors();
 46: 
 47:         $dom = new \DOMDocument();
 48:         $dom->validateOnParse = true;
 49:         if (!$dom->loadXML(file_get_contents($file), LIBXML_NONET | (defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) {
 50:             libxml_disable_entity_loader($disableEntities);
 51: 
 52:             throw new \InvalidArgumentException(implode("\n", static::getXmlErrors($internalErrors)));
 53:         }
 54: 
 55:         $dom->normalizeDocument();
 56: 
 57:         libxml_use_internal_errors($internalErrors);
 58:         libxml_disable_entity_loader($disableEntities);
 59: 
 60:         foreach ($dom->childNodes as $child) {
 61:             if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
 62:                 throw new \InvalidArgumentException('Document types are not allowed.');
 63:             }
 64:         }
 65: 
 66:         if (null !== $schemaOrCallable) {
 67:             $internalErrors = libxml_use_internal_errors(true);
 68:             libxml_clear_errors();
 69: 
 70:             $e = null;
 71:             if (is_callable($schemaOrCallable)) {
 72:                 try {
 73:                     $valid = call_user_func($schemaOrCallable, $dom, $internalErrors);
 74:                 } catch (\Exception $e) {
 75:                     $valid = false;
 76:                 }
 77:             } elseif (!is_array($schemaOrCallable) && is_file((string) $schemaOrCallable)) {
 78:                 $valid = @$dom->schemaValidate($schemaOrCallable);
 79:             } else {
 80:                 libxml_use_internal_errors($internalErrors);
 81: 
 82:                 throw new \InvalidArgumentException('The schemaOrCallable argument has to be a valid path to XSD file or callable.');
 83:             }
 84: 
 85:             if (!$valid) {
 86:                 $messages = static::getXmlErrors($internalErrors);
 87:                 if (empty($messages)) {
 88:                     $messages = array(sprintf('The XML file "%s" is not valid.', $file));
 89:                 }
 90:                 throw new \InvalidArgumentException(implode("\n", $messages), 0, $e);
 91:             }
 92: 
 93:             libxml_use_internal_errors($internalErrors);
 94:         }
 95: 
 96:         return $dom;
 97:     }
 98: 
 99:     /**
100:      * Converts a \DomElement object to a PHP array.
101:      *
102:      * The following rules applies during the conversion:
103:      *
104:      *  * Each tag is converted to a key value or an array
105:      *    if there is more than one "value"
106:      *
107:      *  * The content of a tag is set under a "value" key (<foo>bar</foo>)
108:      *    if the tag also has some nested tags
109:      *
110:      *  * The attributes are converted to keys (<foo foo="bar"/>)
111:      *
112:      *  * The nested-tags are converted to keys (<foo><foo>bar</foo></foo>)
113:      *
114:      * @param \DomElement $element     A \DomElement instance
115:      * @param Boolean     $checkPrefix Check prefix in an element or an attribute name
116:      *
117:      * @return array A PHP array
118:      */
119:     public static function convertDomElementToArray(\DomElement $element, $checkPrefix = true)
120:     {
121:         $prefix = (string) $element->prefix;
122:         $empty = true;
123:         $config = array();
124:         foreach ($element->attributes as $name => $node) {
125:             if ($checkPrefix && !in_array((string) $node->prefix, array('', $prefix), true)) {
126:                 continue;
127:             }
128:             $config[$name] = static::phpize($node->value);
129:             $empty = false;
130:         }
131: 
132:         $nodeValue = false;
133:         foreach ($element->childNodes as $node) {
134:             if ($node instanceof \DOMText) {
135:                 if (trim($node->nodeValue)) {
136:                     $nodeValue = trim($node->nodeValue);
137:                     $empty = false;
138:                 }
139:             } elseif ($checkPrefix && $prefix != (string) $node->prefix) {
140:                 continue;
141:             } elseif (!$node instanceof \DOMComment) {
142:                 $value = static::convertDomElementToArray($node, $checkPrefix);
143: 
144:                 $key = $node->localName;
145:                 if (isset($config[$key])) {
146:                     if (!is_array($config[$key]) || !is_int(key($config[$key]))) {
147:                         $config[$key] = array($config[$key]);
148:                     }
149:                     $config[$key][] = $value;
150:                 } else {
151:                     $config[$key] = $value;
152:                 }
153: 
154:                 $empty = false;
155:             }
156:         }
157: 
158:         if (false !== $nodeValue) {
159:             $value = static::phpize($nodeValue);
160:             if (count($config)) {
161:                 $config['value'] = $value;
162:             } else {
163:                 $config = $value;
164:             }
165:         }
166: 
167:         return !$empty ? $config : null;
168:     }
169: 
170:     /**
171:      * Converts an xml value to a php type.
172:      *
173:      * @param mixed $value
174:      *
175:      * @return mixed
176:      */
177:     public static function phpize($value)
178:     {
179:         $value = (string) $value;
180:         $lowercaseValue = strtolower($value);
181: 
182:         switch (true) {
183:             case 'null' === $lowercaseValue:
184:                 return null;
185:             case ctype_digit($value):
186:                 $raw = $value;
187:                 $cast = intval($value);
188: 
189:                 return '0' == $value[0] ? octdec($value) : (((string) $raw == (string) $cast) ? $cast : $raw);
190:             case 'true' === $lowercaseValue:
191:                 return true;
192:             case 'false' === $lowercaseValue:
193:                 return false;
194:             case is_numeric($value):
195:                 return '0x' == $value[0].$value[1] ? hexdec($value) : floatval($value);
196:             case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $value):
197:                 return floatval(str_replace(',', '', $value));
198:             default:
199:                 return $value;
200:         }
201:     }
202: 
203:     protected static function getXmlErrors($internalErrors)
204:     {
205:         $errors = array();
206:         foreach (libxml_get_errors() as $error) {
207:             $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)',
208:                 LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
209:                 $error->code,
210:                 trim($error->message),
211:                 $error->file ? $error->file : 'n/a',
212:                 $error->line,
213:                 $error->column
214:             );
215:         }
216: 
217:         libxml_clear_errors();
218:         libxml_use_internal_errors($internalErrors);
219: 
220:         return $errors;
221:     }
222: }
223: 
php-coveralls API documentation generated by ApiGen 2.8.0