diff --git a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php index ed66fa30898df..cc983042fefb4 100644 --- a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php @@ -59,6 +59,7 @@ class XmlEncoder implements EncoderInterface, DecoderInterface, NormalizationAwa public const TYPE_CAST_ATTRIBUTES = 'xml_type_cast_attributes'; public const VERSION = 'xml_version'; public const CDATA_WRAPPING = 'cdata_wrapping'; + public const ARRAY_AS_ITEM = 'array_as_item'; public const CDATA_WRAPPING_PATTERN = 'cdata_wrapping_pattern'; public const IGNORE_EMPTY_ATTRIBUTES = 'ignore_empty_attributes'; @@ -71,6 +72,7 @@ class XmlEncoder implements EncoderInterface, DecoderInterface, NormalizationAwa self::REMOVE_EMPTY_TAGS => false, self::ROOT_NODE_NAME => 'response', self::TYPE_CAST_ATTRIBUTES => true, + self::ARRAY_AS_ITEM => false, self::CDATA_WRAPPING => true, self::CDATA_WRAPPING_PATTERN => '/[<>&]/', self::IGNORE_EMPTY_ATTRIBUTES => false, @@ -345,6 +347,7 @@ private function buildXml(\DOMNode $parentNode, mixed $data, string $format, arr { $append = true; $removeEmptyTags = $context[self::REMOVE_EMPTY_TAGS] ?? $this->defaultContext[self::REMOVE_EMPTY_TAGS] ?? false; + $arrayAsItem = $context[self::ARRAY_AS_ITEM] ?? $this->defaultContext[self::ARRAY_AS_ITEM] ?? false; $encoderIgnoredNodeTypes = $context[self::ENCODER_IGNORED_NODE_TYPES] ?? $this->defaultContext[self::ENCODER_IGNORED_NODE_TYPES]; if (\is_array($data) || ($data instanceof \Traversable && (null === $this->serializer || !$this->serializer->supportsNormalization($data, $format)))) { @@ -373,7 +376,7 @@ private function buildXml(\DOMNode $parentNode, mixed $data, string $format, arr } } elseif (\is_array($data) && false === is_numeric($key)) { // Is this array fully numeric keys? - if (ctype_digit(implode('', array_keys($data)))) { + if (!$arrayAsItem && ctype_digit(implode('', array_keys($data)))) { /* * Create nodes to append to $parentNode based on the $key of this array * Produces 01 diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php index 78699983f7592..5c218d541dd24 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php @@ -1017,4 +1017,48 @@ public function testEncodeIgnoringEmptyAttribute() $this->assertEquals($expected, $this->encoder->encode($data, 'xml', ['ignore_empty_attributes' => true])); } + + public function testEncodeArrayAsItem() + { + $expected = <<<'XML' + +BenjaminAlexandreDamienClay + +XML; + $source = ['person' => [ + ['firstname' => 'Benjamin', 'lastname' => 'Alexandre'], + ['firstname' => 'Damien', 'lastname' => 'Clay'], + ]]; + + $this->assertEquals($expected, $this->encoder->encode($source, 'xml', [ + XmlEncoder::ARRAY_AS_ITEM => true, + ])); + } + + public function testDecodeArrayAsItem() + { + $source = <<<'XML' + + + + + Benjamin + Alexandre + + + Damien + Clay + + + +XML; + $expected = ['person' => [ + ['firstname' => 'Benjamin', 'lastname' => 'Alexandre', '@key' => 0], + ['firstname' => 'Damien', 'lastname' => 'Clay', '@key' => 1], + ]]; + + $this->assertEquals($expected, $this->encoder->decode($source, 'xml', [ + XmlEncoder::ARRAY_AS_ITEM => true, + ])); + } }