Skip to content

Commit d0687f2

Browse files
authored
Merge pull request #90 from Ardenexal/feat/roundtrip-doc-fix
docs: remove fixed single-element XML round-trip limitation; add regression guard
2 parents 111863b + 0934692 commit d0687f2

3 files changed

Lines changed: 41 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
- [Docs] Removed the stale "single-element repeating fields" XML limitation note from the serialization guide; single-value repeating fields (e.g. a `HumanName` with one `given`) already round-trip correctly through XML, and a regression test now guards this
12+
1013
## [0.4.0] - 2026-06-12
1114

1215
### Added

docs/serialization/xml.md

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,6 @@ definitions are never processed. Attribute values are also preserved as strings
3535
their precision on round-trip rather than being cast to float/int.
3636
{% endhint %}
3737

38-
{% hint style="info" %}
39-
**Known limitation (XML, single-element repeating fields):** a repeating element that contains
40-
exactly one value (for example a `HumanName` whose `given` is `['John']`) currently fails to
41-
deserialize back from XML, because XML collapses the lone element to a scalar. Two-or-more values
42-
(`given: ['John', 'James']`) round-trip correctly, as does omitting the field. JSON is unaffected.
43-
{% endhint %}
44-
4538
## Error handling
4639

4740
Like JSON, all failures are wrapped in `FHIRSerializationException`:

src/Component/Serialization/tests/Integration/ArrayOfComplexRoundTripTest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,42 @@ public function testArrayOfComplexXmlRoundTripPreservesAllItems(): void
5656
self::assertIsArray($names);
5757
self::assertCount(2, $names, 'both HumanName entries must survive a JSON→object→XML→object trip');
5858
}
59+
60+
/**
61+
* Regression guard: a repeating field with exactly ONE value must survive an XML round-trip.
62+
* XmlEncoder collapses a lone element to a scalar/assoc array rather than a list, so single-element
63+
* arrays must be re-wrapped on deserialization. Covers both a repeating primitive (`given`) and a
64+
* repeating complex type (`identifier`). The 2+-element case is covered above; this guards the tail.
65+
*/
66+
public function testSingleElementRepeatingFieldsXmlRoundTrip(): void
67+
{
68+
$service = FHIRSerializationService::createDefault();
69+
70+
$json = <<<'JSON'
71+
{
72+
"resourceType": "Patient",
73+
"id": "single",
74+
"identifier": [ { "system": "urn:x", "value": "123" } ],
75+
"name": [ { "family": "Smith", "given": ["John"] } ]
76+
}
77+
JSON;
78+
79+
$patient = $service->deserialize($json);
80+
$xml = $service->serializeToXml($patient);
81+
$back = $service->deserialize($xml);
82+
83+
$refl = new \ReflectionClass($back);
84+
85+
$names = $refl->getProperty('name')->getValue($back);
86+
self::assertIsArray($names);
87+
self::assertCount(1, $names, 'single HumanName must survive an XML round-trip');
88+
89+
$given = (new \ReflectionClass($names[0]))->getProperty('given')->getValue($names[0]);
90+
self::assertIsArray($given, 'single-element repeating primitive `given` must stay an array');
91+
self::assertCount(1, $given, 'lone `given` value must not be lost when XML collapses it');
92+
93+
$identifiers = $refl->getProperty('identifier')->getValue($back);
94+
self::assertIsArray($identifiers);
95+
self::assertCount(1, $identifiers, 'single complex `identifier` must survive an XML round-trip');
96+
}
5997
}

0 commit comments

Comments
 (0)