Skip to content

Commit d011981

Browse files
qdequippefabpot
authored andcommitted
[Serializer] Add xml context option to ignore empty attributes
1 parent 789055e commit d011981

File tree

5 files changed

+40
-3
lines changed

5 files changed

+40
-3
lines changed

src/Symfony/Component/Serializer/CHANGELOG.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
CHANGELOG
22
=========
33

4+
7.3
5+
---
6+
7+
* Deprecate the `CompiledClassMetadataFactory` and `CompiledClassMetadataCacheWarmer` classes
8+
49
7.2
510
---
611

7-
* Deprecate the `csv_escape_char` context option of `CsvEncoder` and the `CsvEncoder::ESCAPE_CHAR_KEY` constant
8-
* Deprecate `CsvEncoderContextBuilder::withEscapeChar()` method
12+
* Deprecate the `csv_escape_char` context option of `CsvEncoder`, the `CsvEncoder::ESCAPE_CHAR_KEY` constant
13+
and the `CsvEncoderContextBuilder::withEscapeChar()` method, following its deprecation in PHP 8.4
914
* Add `SnakeCaseToCamelCaseNameConverter`
1015
* Support subclasses of `\DateTime` and `\DateTimeImmutable` for denormalization
1116
* Add the `UidNormalizer::NORMALIZATION_FORMAT_RFC9562` constant
@@ -19,7 +24,6 @@ CHANGELOG
1924

2025
* Add arguments `$class`, `$format` and `$context` to `NameConverterInterface::normalize()` and `NameConverterInterface::denormalize()`
2126
* Add `DateTimeNormalizer::CAST_KEY` context option
22-
* Add `Default` and "class name" default groups
2327
* Add `AbstractNormalizer::FILTER_BOOL` context option
2428
* Add `CamelCaseToSnakeCaseNameConverter::REQUIRE_SNAKE_CASE_PROPERTIES` context option
2529
* Deprecate `AbstractNormalizerContextBuilder::withDefaultContructorArguments(?array $defaultContructorArguments)`, use `withDefaultConstructorArguments(?array $defaultConstructorArguments)` instead (note the missing `s` character in Contructor word in deprecated method)

src/Symfony/Component/Serializer/Context/Encoder/XmlEncoderContextBuilder.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,12 @@ public function withCdataWrappingPattern(?string $cdataWrappingPattern): static
160160
{
161161
return $this->with(XmlEncoder::CDATA_WRAPPING_PATTERN, $cdataWrappingPattern);
162162
}
163+
164+
/**
165+
* Configures whether to ignore empty attributes.
166+
*/
167+
public function withIgnoreEmptyAttributes(?bool $ignoreEmptyAttributes): static
168+
{
169+
return $this->with(XmlEncoder::IGNORE_EMPTY_ATTRIBUTES, $ignoreEmptyAttributes);
170+
}
163171
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class XmlEncoder implements EncoderInterface, DecoderInterface, NormalizationAwa
6060
public const VERSION = 'xml_version';
6161
public const CDATA_WRAPPING = 'cdata_wrapping';
6262
public const CDATA_WRAPPING_PATTERN = 'cdata_wrapping_pattern';
63+
public const IGNORE_EMPTY_ATTRIBUTES = 'ignore_empty_attributes';
6364

6465
private array $defaultContext = [
6566
self::AS_COLLECTION => false,
@@ -72,6 +73,7 @@ class XmlEncoder implements EncoderInterface, DecoderInterface, NormalizationAwa
7273
self::TYPE_CAST_ATTRIBUTES => true,
7374
self::CDATA_WRAPPING => true,
7475
self::CDATA_WRAPPING_PATTERN => '/[<>&]/',
76+
self::IGNORE_EMPTY_ATTRIBUTES => false,
7577
];
7678

7779
public function __construct(array $defaultContext = [])
@@ -355,6 +357,13 @@ private function buildXml(\DOMNode $parentNode, mixed $data, string $format, arr
355357
if (\is_bool($data)) {
356358
$data = (int) $data;
357359
}
360+
361+
if ($context[self::IGNORE_EMPTY_ATTRIBUTES] ?? $this->defaultContext[self::IGNORE_EMPTY_ATTRIBUTES]) {
362+
if (null === $data || '' === $data) {
363+
continue;
364+
}
365+
}
366+
358367
$parentNode->setAttribute($attributeName, $data);
359368
} elseif ('#' === $key) {
360369
$append = $this->selectNodeType($parentNode, $data, $format, $context);

src/Symfony/Component/Serializer/Tests/Context/Encoder/XmlEncoderContextBuilderTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public function testWithers(array $values)
4747
->withVersion($values[XmlEncoder::VERSION])
4848
->withCdataWrapping($values[XmlEncoder::CDATA_WRAPPING])
4949
->withCdataWrappingPattern($values[XmlEncoder::CDATA_WRAPPING_PATTERN])
50+
->withIgnoreEmptyAttributes($values[XmlEncoder::IGNORE_EMPTY_ATTRIBUTES])
5051
->toArray();
5152

5253
$this->assertSame($values, $context);
@@ -69,6 +70,7 @@ public static function withersDataProvider(): iterable
6970
XmlEncoder::VERSION => '1.0',
7071
XmlEncoder::CDATA_WRAPPING => false,
7172
XmlEncoder::CDATA_WRAPPING_PATTERN => '/[<>&"\']/',
73+
XmlEncoder::IGNORE_EMPTY_ATTRIBUTES => true,
7274
]];
7375

7476
yield 'With null values' => [[
@@ -86,6 +88,7 @@ public static function withersDataProvider(): iterable
8688
XmlEncoder::VERSION => null,
8789
XmlEncoder::CDATA_WRAPPING => null,
8890
XmlEncoder::CDATA_WRAPPING_PATTERN => null,
91+
XmlEncoder::IGNORE_EMPTY_ATTRIBUTES => null,
8992
]];
9093
}
9194
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,4 +1004,17 @@ private function createXmlWithDateTimeField(): string
10041004
<response><foo dateTime="%s"/></response>
10051005
', $this->exampleDateTimeString);
10061006
}
1007+
1008+
public function testEncodeIgnoringEmptyAttribute()
1009+
{
1010+
$expected = <<<'XML'
1011+
<?xml version="1.0"?>
1012+
<response>Test</response>
1013+
1014+
XML;
1015+
1016+
$data = ['#' => 'Test', '@attribute' => '', '@attribute2' => null];
1017+
1018+
$this->assertEquals($expected, $this->encoder->encode($data, 'xml', ['ignore_empty_attributes' => true]));
1019+
}
10071020
}

0 commit comments

Comments
 (0)