dcarbone / php-fhir-generated

Pre-generated classes from dcarbone/php-fhir
Apache License 2.0
36 stars 11 forks source link

3.0 and 2.0 generate XML differently #19

Closed yunosh closed 3 months ago

yunosh commented 3 months ago

This:

(new FHIRParameters([
            FHIRParameters::FIELD_META => new FHIRMeta([FHIRMeta::FIELD_PROFILE => 'https://e-lb.de/fhir/StructureDefinition/KK_ELB_ParticipationStatusRequestParameters']),
            FHIRParameters::FIELD_PARAMETER => [
                new FHIRParametersParameter([
                    FHIRParametersParameter::FIELD_NAME => 'patient',
                    FHIRParametersParameter::FIELD_VALUE_IDENTIFIER => new FHIRIdentifier([
                        FHIRIdentifier::FIELD_SYSTEM => 'http://fhir.de/sid/gkv/kvid-10',
                        FHIRIdentifier::FIELD_VALUE => $patientKvId,
                    ])
                ]),
                new FHIRParametersParameter([
                    FHIRParametersParameter::FIELD_NAME => 'payor',
                    FHIRParametersParameter::FIELD_VALUE_IDENTIFIER => new FHIRIdentifier([
                        FHIRIdentifier::FIELD_SYSTEM => 'http://fhir.de/sid/arge-ik/iknr',
                        FHIRIdentifier::FIELD_VALUE => $payorIkNr,
                    ])
                ])
            ],
        ]))->xmlSerialize()

generates different XML output in 3.0 vs. 2.0.

2.0:

<Parameters xmlns="http://hl7.org/fhir">
    <meta>
        <profile value="https://e-lb.de/fhir/StructureDefinition/KK_ELB_ParticipationStatusRequestParameters"/>
    </meta>
    <parameter>
        <name value="patient"/>
        <valueIdentifier value="1234567890">
            <system value="http://fhir.de/sid/gkv/kvid-10"/>
            <value value="1234567890"/>
        </valueIdentifier>
    </parameter>
    <parameter>
        <name value="payor"/>
        <valueIdentifier value="9876543210">
            <system value="http://fhir.de/sid/arge-ik/iknr"/>
            <value value="9876543210"/>
        </valueIdentifier>
    </parameter>
</Parameters>

3.0:

<Parameters>
    <meta profile="https://e-lb.de/fhir/StructureDefinition/KK_ELB_ParticipationStatusRequestParameters"/>
    <parameter name="patient">
        <valueIdentifier system="http://fhir.de/sid/gkv/kvid-10" value="1234567890"/>
    </parameter>
    <parameter name="payor">
        <valueIdentifier system="http://fhir.de/sid/arge-ik/iknr" value="9876543210"/>
    </parameter>
</Parameters>

If this is expected, then how do I generate parameters, profiles etc as tags vs. attributes?

Also, as a side note, why is the valueIdentifier value in 2.0 appearing twice?

dcarbone commented 3 months ago

That's correct, v2.0 had several output issues. Many, if not all, were resolved with 3.0 by way of switching to using XMLWriter vs. SimpleXMLElement for serialization and primitive location tracking.

In 2.0, I did not track whether I saw primitive values as an element or an attribute, so I output them in both to be safe. Tracking the location of these is one of the features I added to 3.0.

You can define where to output these values with the setter funcs. Additionally, FHIR elements that have non-primitive fields will have them output as child XML elements automatically.

dcarbone commented 3 months ago

Sorry, will leave open for followup questions!

yunosh commented 3 months ago

Well, the point is, that the output of 2.0 is the expected output (minus the extra attribute). For reference, this is the official FHIR example for a request payload:

<?xml version="1.0" encoding="utf-8"?>
<Parameters xmlns="http://hl7.org/fhir">
    <meta>
        <profile value="https://e-lb.de/fhir/StructureDefinition/KK_ELB_ParticipationStatusRequestParameters"/>
    </meta>
    <parameter>
        <name value="patient"/>
        <valueIdentifier>
            <system value="http://fhir.de/sid/gkv/kvid-10"/>
            <value value="K123456789"/>
        </valueIdentifier>
    </parameter>
    <parameter>
        <name value="payor"/>
         <valueIdentifier>
            <system value="http://fhir.de/sid/arge-ik/iknr"/>
            <value value="101575519"/>
         </valueIdentifier>
    </parameter>
</Parameters>

see https://github.com/ITSGGMBH/eLB/blob/main/Beispiele/Teilnehmerabfrage/ParticipationStatusRequestParameters.xml

this is the definition: https://github.com/ITSGGMBH/eLB/blob/main/KK_ELB_ParticipationStatusRequestParameters.StructureDefinition.xml

and this is how I try to generate this output:

        (new FHIRParameters([
            FHIRParameters::FIELD_META => new FHIRMeta([FHIRMeta::FIELD_PROFILE => 'https://e-lb.de/fhir/StructureDefinition/KK_ELB_ParticipationStatusRequestParameters']),
            FHIRParameters::FIELD_PARAMETER => [
                new FHIRParametersParameter([
                    FHIRParametersParameter::FIELD_NAME => 'patient',
                    FHIRParametersParameter::FIELD_VALUE_IDENTIFIER => new FHIRIdentifier([
                        FHIRIdentifier::FIELD_SYSTEM => 'http://fhir.de/sid/gkv/kvid-10',
                        FHIRIdentifier::FIELD_VALUE => $patientKvId,
                    ])
                ]),
                new FHIRParametersParameter([
                    FHIRParametersParameter::FIELD_NAME => 'payor',
                    FHIRParametersParameter::FIELD_VALUE_IDENTIFIER => new FHIRIdentifier([
                        FHIRIdentifier::FIELD_SYSTEM => 'http://fhir.de/sid/arge-ik/iknr',
                        FHIRIdentifier::FIELD_VALUE => $payorIkNr,
                    ])
                ])
            ],
        ]))->xmlSerialize(config: new PHPFHIRConfig([PHPFHIRConfigKeyEnum::ROOT_XMLNS->value => 'http://hl7.org/fhir']));

For now I had to downgrade to 2.0.

dcarbone commented 3 months ago

Hmm, so as mentioned you can specify the location of elements using the individual setter methods.

Your expected output is different from other's expected output. I cannot unilaterally enforce one placement without breaking it for another.

v2.0 will not be receiving any further updates, so please try to use the setter methods and specify location.

As an example, the DSTU2 setter for Parameter.System.value is here: https://github.com/dcarbone/php-fhir-generated/blob/main/src/DCarbone/PHPFHIRGenerated/DSTU2/FHIRElement/FHIRIdentifier.php#L393

Providing the xmlLocation argument allows you to control where this value is placed when serializing to XML. When unserailizing from XML, I am able to record this location automatically.

When unserializing or constructing from JSON, as you're doing in your example, I cannot pre-determine where you would like this element to be located during XML serialization.

I have thought that a possibly nice feature would be to increase the scope of the Config type, allowing you to specify attr vs. element output for a given type universally.

yunosh commented 3 months ago

Ah yes, I missed the last sentence of your earlier comment and, I wasn't really aware of the setter methods, let alone the xmlLocation parameter. We kept setting the sub-elements via constructor parameters. I guess this does it, thanks!