XML Encoder Optional Type Cast

- This provides the ability to forgo the attribute type casting
- Updated the CHANGELOG

Signed-off-by: RJ Garcia <rj@bighead.net>
This commit is contained in:
RJ Garcia 2017-06-09 14:01:58 -07:00 committed by Fabien Potencier
parent 6727a2610b
commit 8f6e67d319
3 changed files with 48 additions and 9 deletions

View File

@ -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
-----

View File

@ -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.
*

View File

@ -284,6 +284,28 @@ XML;
$this->assertSame(array('@index' => -12.11, '#' => 'Name'), $this->encoder->decode($source, 'xml'));
}
public function testNoTypeCastAttribute()
{
$source = <<<XML
<?xml version="1.0"?>
<document a="018" b="-12.11">
<node a="018" b="-12.11"/>
</document>
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();