namespace Symfony\Component\Config\Util;
+use Symfony\Component\Config\Util\Exception\InvalidXmlException;
+use Symfony\Component\Config\Util\Exception\XmlParsingException;
+
/**
* XMLUtils is a bunch of utility methods to XML operations.
*
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Martin Hasoň <martin.hason@gmail.com>
+ * @author Ole Rößner <ole@roessner.it>
*/
class XmlUtils
{
}
/**
- * Loads an XML file.
+ * Parses an XML string.
*
- * @param string $file An XML file path
+ * @param string $content An XML string
* @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation
*
* @return \DOMDocument
*
- * @throws \InvalidArgumentException When loading of XML file returns error
+ * @throws XmlParsingException When parsing of XML file returns error
+ * @throws InvalidXmlException When parsing of XML with schema or callable produces any errors unrelated to the XML parsing itself
+ * @throws \RuntimeException When DOM extension is missing
*/
- public static function loadFile($file, $schemaOrCallable = null)
+ public static function parse($content, $schemaOrCallable = null)
{
- $content = @file_get_contents($file);
- if ('' === trim($content)) {
- throw new \InvalidArgumentException(sprintf('File %s does not contain valid XML, it is empty.', $file));
+ if (!\extension_loaded('dom')) {
+ throw new \RuntimeException('Extension DOM is required.');
}
$internalErrors = libxml_use_internal_errors(true);
$dom = new \DOMDocument();
$dom->validateOnParse = true;
- if (!$dom->loadXML($content, LIBXML_NONET | (defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) {
+ if (!$dom->loadXML($content, LIBXML_NONET | (\defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) {
libxml_disable_entity_loader($disableEntities);
- throw new \InvalidArgumentException(implode("\n", static::getXmlErrors($internalErrors)));
+ throw new XmlParsingException(implode("\n", static::getXmlErrors($internalErrors)));
}
$dom->normalizeDocument();
libxml_disable_entity_loader($disableEntities);
foreach ($dom->childNodes as $child) {
- if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
- throw new \InvalidArgumentException('Document types are not allowed.');
+ if (XML_DOCUMENT_TYPE_NODE === $child->nodeType) {
+ throw new XmlParsingException('Document types are not allowed.');
}
}
libxml_clear_errors();
$e = null;
- if (is_callable($schemaOrCallable)) {
+ if (\is_callable($schemaOrCallable)) {
try {
- $valid = call_user_func($schemaOrCallable, $dom, $internalErrors);
+ $valid = \call_user_func($schemaOrCallable, $dom, $internalErrors);
} catch (\Exception $e) {
$valid = false;
}
- } elseif (!is_array($schemaOrCallable) && is_file((string) $schemaOrCallable)) {
+ } elseif (!\is_array($schemaOrCallable) && is_file((string) $schemaOrCallable)) {
$schemaSource = file_get_contents((string) $schemaOrCallable);
$valid = @$dom->schemaValidateSource($schemaSource);
} else {
libxml_use_internal_errors($internalErrors);
- throw new \InvalidArgumentException('The schemaOrCallable argument has to be a valid path to XSD file or callable.');
+ throw new XmlParsingException('The schemaOrCallable argument has to be a valid path to XSD file or callable.');
}
if (!$valid) {
$messages = static::getXmlErrors($internalErrors);
if (empty($messages)) {
- $messages = array(sprintf('The XML file "%s" is not valid.', $file));
+ throw new InvalidXmlException('The XML is not valid.', 0, $e);
}
- throw new \InvalidArgumentException(implode("\n", $messages), 0, $e);
+ throw new XmlParsingException(implode("\n", $messages), 0, $e);
}
}
}
/**
- * Converts a \DomElement object to a PHP array.
+ * Loads an XML file.
+ *
+ * @param string $file An XML file path
+ * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation
+ *
+ * @return \DOMDocument
+ *
+ * @throws \InvalidArgumentException When loading of XML file returns error
+ * @throws XmlParsingException When XML parsing returns any errors
+ * @throws \RuntimeException When DOM extension is missing
+ */
+ public static function loadFile($file, $schemaOrCallable = null)
+ {
+ $content = @file_get_contents($file);
+ if ('' === trim($content)) {
+ throw new \InvalidArgumentException(sprintf('File %s does not contain valid XML, it is empty.', $file));
+ }
+
+ try {
+ return static::parse($content, $schemaOrCallable);
+ } catch (InvalidXmlException $e) {
+ throw new XmlParsingException(sprintf('The XML file "%s" is not valid.', $file), 0, $e->getPrevious());
+ }
+ }
+
+ /**
+ * Converts a \DOMElement object to a PHP array.
*
* The following rules applies during the conversion:
*
*
* * The nested-tags are converted to keys (<foo><foo>bar</foo></foo>)
*
- * @param \DomElement $element A \DomElement instance
+ * @param \DOMElement $element A \DOMElement instance
* @param bool $checkPrefix Check prefix in an element or an attribute name
*
* @return array A PHP array
$empty = true;
$config = array();
foreach ($element->attributes as $name => $node) {
- if ($checkPrefix && !in_array((string) $node->prefix, array('', $prefix), true)) {
+ if ($checkPrefix && !\in_array((string) $node->prefix, array('', $prefix), true)) {
continue;
}
$config[$name] = static::phpize($node->value);
$key = $node->localName;
if (isset($config[$key])) {
- if (!is_array($config[$key]) || !is_int(key($config[$key]))) {
+ if (!\is_array($config[$key]) || !\is_int(key($config[$key]))) {
$config[$key] = array($config[$key]);
}
$config[$key][] = $value;
if (false !== $nodeValue) {
$value = static::phpize($nodeValue);
- if (count($config)) {
+ if (\count($config)) {
$config['value'] = $value;
} else {
$config = $value;
return '0x' === $value[0].$value[1] ? hexdec($value) : (float) $value;
case preg_match('/^0x[0-9a-f]++$/i', $value):
return hexdec($value);
- case preg_match('/^(-|\+)?[0-9]+(\.[0-9]+)?$/', $value):
+ case preg_match('/^[+-]?[0-9]+(\.[0-9]+)?$/', $value):
return (float) $value;
default:
return $value;