10000 feature #26445 [Serializer] Ignore comments when decoding XML (q0rban) · symfony/symfony@bbeca51 · GitHub
[go: up one dir, main page]

Skip to content

Commit bbeca51

Browse files
committed
feature #26445 [Serializer] Ignore comments when decoding XML (q0rban)
This PR was squashed before being merged into the 4.1-dev branch (closes #26445). Discussion ---------- [Serializer] Ignore comments when decoding XML | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | N/A | License | MIT | Doc PR | N/A Previously, if the first line of XML was a comment, that would be used as the root node of the decoded XML. This work strips comments from decoded XML by default, but also allows for customizing which XML node types are ignored during decoding. The first two commits in this PR contain tests only to prove the existence of this "bug". Commits ------- f6760d3 [Serializer] Ignore comments when decoding XML
2 parents 7262c59 + f6760d3 commit bbeca51

File tree

4 files changed

+70
-4
lines changed

4 files changed

+70
-4
lines changed

UPGRADE-4.1.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ SecurityBundle
8080
* The `SecurityUserValueResolver` class is deprecated, use
8181
`Symfony\Component\Security\Http\Controller\UserValueResolver` instead.
8282

83+
Serializer
84+
----------
85+
86+
* Decoding XML with `XmlEncoder` now ignores comment node types by default.
87+
8388
Translation
8489
-----------
8590

src/Symfony/Component/Serializer/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ CHANGELOG
1111
* added optional `bool $escapeFormulas = false` argument to `CsvEncoder::__construct`
1212
* added `AbstractObjectNormalizer::setMaxDepthHandler` to set a handler to call when the configured
1313
maximum depth is reached
14+
* added optional `int[] $ignoredNodeTypes` argument to `XmlEncoder::__construct`. XML decoding now
15+
ignores comment node types by default.
1416

1517
4.0.0
1618
-----

src/Symfony/Component/Serializer/Encoder/XmlEncoder.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,19 @@ class XmlEncoder implements EncoderInterface, DecoderInterface, NormalizationAwa
3737
private $context;
3838
private $rootNodeName = 'response';
3939
private $loadOptions;
40+
private $ignoredNodeTypes;
4041

4142
/**
4243
* Construct new XmlEncoder and allow to change the root node element name.
4344
*
44-
* @param int|null $loadOptions A bit field of LIBXML_* constants
45+
* @param int|null $loadOptions A bit field of LIBXML_* constants
46+
* @param int[] $ignoredNodeTypes an array of ignored XML node types, each one of the DOM Predefined XML_* Constants
4547
*/
46-
public function __construct(string $rootNodeName = 'response', int $loadOptions = null)
48+
public function __construct(string $rootNodeName = 'response', int $loadOptions = null, array $ignoredNodeTypes = array(XML_PI_NODE, XML_COMMENT_NODE))
4749
{
4850
$this->rootNodeName = $rootNodeName;
4951
$this->loadOptions = null !== $loadOptions ? $loadOptions : LIBXML_NONET | LIBXML_NOBLANKS;
52+
$this->ignoredNodeTypes = $ignoredNodeTypes;
5053
}
5154

5255
/**
@@ -105,7 +108,7 @@ public function decode($data, $format, array $context = array())
105108
if (XML_DOCUMENT_TYPE_NODE === $child->nodeType) {
106109
throw new NotEncodableValueException('Document types are not allowed.');
107110
}
108-
if (!$rootNode && XML_PI_NODE !== $child->nodeType) {
111+
if (!$rootNode && !\in_array($child->nodeType, $this->ignoredNodeTypes, true)) {
109112
$rootNode = $child;
110113
}
111114
}
@@ -316,7 +319,7 @@ private function parseXmlValue(\DOMNode $node, array $context = array())
316319
$value = array();
317320

318321
foreach ($node->childNodes as $subnode) {
319-
if (XML_PI_NODE === $subnode->nodeType) {
322+
if (\in_array($subnode->nodeType, $this->ignoredNodeTypes, true)) {
320323
continue;
321324
}
322325

src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,62 @@ public function testDecodeIgnoreWhiteSpace()
515515
$this->assertEquals($expected, $this->encoder->decode($source, 'xml'));
516516
}
517517

518+
public function testDecodeIgnoreComments()
519+
{
520+
$source = <<<'XML'
521+
<?xml version="1.0"?>
522+
<!-- This comment should not become the root node. -->
523+
<people>
524+
<person>
525+
<!-- Even if the first comment didn't become the root node, we don't
526+
want this comment either. -->
527+
<firstname>Benjamin</firstname>
528+
<lastname>Alexandre</lastname>
529+
</person>
530+
<person>
531+
<firstname>Damien</firstname>
532+
<lastname>Clay</lastname>
533+
</person>
534+
</people>
535+
XML;
536+
537+
$expected = array('person' => array(
538+
array('firstname' => 'Benjamin', 'lastname' => 'Alexandre'),
539+
array('firstname' => 'Damien', 'lastname' => 'Clay'),
540+
));
541+
542+
$this->assertEquals($expected, $this->encoder->decode($source, 'xml'));
543+
}
544+
545+
public function testDecodePreserveComments()
546+
{
547+
$source = <<<'XML'
548+
<?xml version="1.0"?>
549+
<people>
550+
<person>
551+
<!-- This comment should be decoded. -->
552+
<firstname>Benjamin</firstname>
553+
<lastname>Alexandre</lastname>
554+
</person>
555+
<person>
556+
<firstname>Damien</firstname>
557+
<lastname>Clay</lastname>
558+
</person>
559+
</people>
560+
XML;
561+
562+
$this->encoder = new XmlEncoder('people', null, array(XML_PI_NODE));
563+
$serializer = new Serializer(array(new CustomNormalizer()), array('xml' => new XmlEncoder()));
564+
$this->encoder->setSerializer($serializer);
565+
566+
$expected = array('person' => array(
567+
array('firstname' => 'Benjamin', 'lastname' => 'Alexandre', '#comment' => ' This comment should be decoded. '),
568+
array('firstname' => 'Damien', 'lastname' => 'Clay'),
569+
));
570+
571+
$this->assertEquals($expected, $this->encoder->decode($source, 'xml'));
572+
}
573+
518574
public function testDecodeAlwaysAsCollection()
519575
{
520576
$this->encoder = new XmlEncoder('response', null);

0 commit comments

Comments
 (0)
0