diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index 01c16d00cf..ef5ed79538 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -39,6 +39,8 @@ CHANGELOG * [DEPRECATION] the `Exception` interface has been renamed to `ExceptionInterface` * added `ObjectNormalizer` leveraging the `PropertyAccess` component to normalize objects containing both properties and getters / setters / issers / hassers methods. + * added `xml_type_cast_attributes` context option for allowing users to opt-out of typecasting + xml attributes. 2.6.0 ----- diff --git a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php index f52c609d7e..acc08597dd 100644 --- a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php @@ -119,10 +119,10 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec unset($data['@xmlns:xml']); if (empty($data)) { - return $this->parseXml($rootNode); + return $this->parseXml($rootNode, $context); } - return array_merge($data, (array) $this->parseXml($rootNode)); + return array_merge($data, (array) $this->parseXml($rootNode, $context)); } if (!$rootNode->hasAttributes()) { @@ -261,11 +261,11 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec * * @return array|string */ - private function parseXml(\DOMNode $node) + private function parseXml(\DOMNode $node, array $context = array()) { - $data = $this->parseXmlAttributes($node); + $data = $this->parseXmlAttributes($node, $context); - $value = $this->parseXmlValue($node); + $value = $this->parseXmlValue($node, $context); if (!count($data)) { return $value; @@ -297,16 +297,17 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec * * @return array */ - private function parseXmlAttributes(\DOMNode $node) + private function parseXmlAttributes(\DOMNode $node, array $context = array()) { if (!$node->hasAttributes()) { return array(); } $data = array(); + $typeCastAttributes = $this->resolveXmlTypeCastAttributes($context); foreach ($node->attributes as $attr) { - if (!is_numeric($attr->nodeValue)) { + if (!is_numeric($attr->nodeValue) || !$typeCastAttributes) { $data['@'.$attr->nodeName] = $attr->nodeValue; continue; @@ -331,7 +332,7 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec * * @return array|string */ - private function parseXmlValue(\DOMNode $node) + private function parseXmlValue(\DOMNode $node, array $context = array()) { if (!$node->hasChildNodes()) { return $node->nodeValue; @@ -348,7 +349,7 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec continue; } - $val = $this->parseXml($subnode); + $val = $this->parseXml($subnode, $context); if ('item' === $subnode->nodeName && isset($val['@key'])) { if (isset($val['#'])) { @@ -527,6 +528,20 @@ class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, Dec : $this->rootNodeName; } + /** + * Get XML option for type casting attributes Defaults to true. + * + * @param array $context + * + * @return bool + */ + private function resolveXmlTypeCastAttributes(array $context = array()) + { + return isset($context['xml_type_cast_attributes']) + ? (bool) $context['xml_type_cast_attributes'] + : true; + } + /** * Create a DOM document, taking serializer options into account. * diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php index b1c810e955..e8178ad0c4 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php @@ -284,6 +284,28 @@ XML; $this->assertSame(array('@index' => -12.11, '#' => 'Name'), $this->encoder->decode($source, 'xml')); } + public function testNoTypeCastAttribute() + { + $source = << + + + +XML; + + $data = $this->encoder->decode($source, 'xml', array('xml_type_cast_attributes' => false)); + $expected = array( + '@a' => '018', + '@b' => '-12.11', + 'node' => array( + '@a' => '018', + '@b' => '-12.11', + '#' => '', + ), + ); + $this->assertSame($expected, $data); + } + public function testEncode() { $source = $this->getXmlSource();