php-fhir icon indicating copy to clipboard operation
php-fhir copied to clipboard

HTML output for a narrative element

Open leonrenkema opened this issue 7 years ago • 20 comments

I am trying to generate a narrative for a patient but the generated xml doesnt look correct.

Below is the generated XML where the actual text is added to a value attribute of the div element and the XML namespace is missing.

<text> <status value="generated"/> <div value="&lt;p&gt;Voorbeeld van een 'Patient' zoals verder samengesteld tijdens de HL7 WGM NL 15-04-2016 jl. Deze discussie heeft diverse uitzoekpunten opgeleverd zoals hier gedocumenteerd.&lt;/p&gt;"/> </text>

When I change the following line in FHIRNarrative.php $divElement = $sxe->addChild('div', (string)$this->div); $divElement->addAttribute('value', (string)$this->div);

to

$divElement = $sxe->addChild('div', (string)$this->div, "http://www.w3.org/1999/xhtml"); //$divElement->addAttribute('value', (string)$this->div);

The output does looks better besides that the <p> elements are encoded with htmlentities.

<text> <status value="generated"/> <div xmlns="http://www.w3.org/1999/xhtml">&lt;p&gt;Voorbeeld van een 'Patient' zoals verder samengesteld tijdens de HL7 WGM NL 15-04-2016 jl. Deze discussie heeft diverse uitzoekpunten opgeleverd zoals hier gedocumenteerd.&lt;/p&gt; </div> </text>

I following this example as a reference https://simplifier.net/NictizSTU3/nl-core-patient-example-1/~overview The XSD release is STU3

leonrenkema avatar Jul 15 '17 15:07 leonrenkema

@leonrenkema: hey, thanks for the suggestion. Unfortunately I've not had a great deal of time to implement a lot of the features I'd like to have in this lib, but I have come up with a quick fix that I hope will be satisfactory.

I have modified code identified as "html" to serialize as an XML CDATA element under their parent element.

So, this:

<text>
    <status value="generated"/>
    <div value="&lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt; &lt;table&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;Name&lt;/td&gt; &lt;td&gt;Peter James &lt;b&gt;Chalmers&lt;/b&gt; (&quot;Jim&quot;)&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Address&lt;/td&gt; &lt;td&gt;534 Erewhon, Pleasantville, Vic, 3999&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Contacts&lt;/td&gt; &lt;td&gt;Home: unknown. Work: (03) 5555 6473&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Id&lt;/td&gt; &lt;td&gt;MRN: 12345 (Acme Healthcare)&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;/div&gt;"/>
</text>

will now be this:

<text>
    <status value="generated"/>
    <![CDATA[<div xmlns="http://www.w3.org/1999/xhtml"> <table> <tbody> <tr> <td>Name</td> <td>Peter James <b>Chalmers</b> ("Jim")</td> </tr> <tr> <td>Address</td> <td>534 Erewhon, Pleasantville, Vic, 3999</td> </tr> <tr> <td>Contacts</td> <td>Home: unknown. Work: (03) 5555 6473</td> </tr> <tr> <td>Id</td> <td>MRN: 12345 (Acme Healthcare)</td> </tr> </tbody> </table> </div>]]>
</text>

I have pushed the changes to master. Please check it out and see if this solution works for you. If it does, I will make a new tag and update the generated library as well.

dcarbone avatar Jul 16 '17 03:07 dcarbone

Thanks for the fix but I'dont think it is correct this way. The div element is missing now. I think the desired output should be the following.

<text>
    <status value="generated"/>
    <div xmlns="http://www.w3.org/1999/xhtml"> <table> <tbody> <tr> <td>Name</td> <td>Peter James <b>Chalmers</b> ("Jim")</td> </tr> <tr> <td>Address</td> <td>534 Erewhon, Pleasantville, Vic, 3999</td> </tr> <tr> <td>Contacts</td> <td>Home: unknown. Work: (03) 5555 6473</td> </tr> <tr> <td>Id</td> <td>MRN: 12345 (Acme Healthcare)</td> </tr> </tbody> </table> </div>
</text>

I'm playing around with the generator and trying to generate it the correct way, but SimpleXML is sometimes too simple for these complex use-cases. I will look if I can make a PR that will fix this.

leonrenkema avatar Jul 17 '17 16:07 leonrenkema

@leonrenkema: the div element isn't missing, it is inside the CDATA block. It is generally not a great idea to put raw HTML inside of an XML document as HTML can be written in a much less strict fashion than XML.

dcarbone avatar Jul 17 '17 17:07 dcarbone

Yes, i know. When I look at the FHIR spec it requires a div element within the xhtml namespace. https://www.hl7.org/fhir/narrative.html The div element as cdata does not validate against the XSD.

leonrenkema avatar Jul 17 '17 17:07 leonrenkema

Ah, you are entirely correct. I also do not like my current implementation as it requires php dom to be installed as well as php xml. I have found a few clever solutions to this issue, and will implement one asap.

dcarbone avatar Jul 17 '17 17:07 dcarbone

Tnx. I have worked a lot with xmlwriter in php and that is more flexible than simplexml for generating this kind of xml. I have used it for generating hl7v3 documents.

leonrenkema avatar Jul 17 '17 18:07 leonrenkema

Alrighty, I have pushed an update. I'm not certain I'm happy with the implementation, but if it works for you I will leave as-is until an issue arises.

The output now looks like this:

<text>
    <status value="generated"/>
    <div xmlns="http://www.w3.org/1999/xhtml">  <table>  <tbody>     <tr>   <td>Name</td><td>Peter James  ("Jim")<b>Chalmers</b></td></tr><tr>   <td>Address</td><td>534 Erewhon, Pleasantville, Vic, 3999</td></tr><tr>   <td>Contacts</td><td>Home: unknown. Work: (03) 5555 6473</td></tr><tr>   <td>Id</td><td>MRN: 12345 (Acme Healthcare)</td></tr></tbody></table></div>
</text>

dcarbone avatar Jul 17 '17 21:07 dcarbone

Great, is it intended that I have to use it this way because of the namespacing?

$text->setDiv("<div xmlns=\"http://www.w3.org/1999/xhtml\"><p>Example Narrative</p></div>");

leonrenkema avatar Jul 18 '17 18:07 leonrenkema

I'm not sure what you mean by your last comment, are you asking why I don't inject the namespace myself?

dcarbone avatar Jul 19 '17 14:07 dcarbone

Yes, what I mean is why there is a difference between the setStatus and setDiv. setStatus generates the element but setDiv does not generate the div element.

$text->setStatus($narrativeStatus);
$text->setDiv("<div xmlns=\"http://www.w3.org/1999/xhtml\"><p>Example Narrative</p></div>");

When I use setDiv('<p>Example</p>') the generated xml is not valid because the <div> element is missing.

leonrenkema avatar Jul 19 '17 17:07 leonrenkema

So in this context I'm hesitant to assume the existence of the <div> element. I don't want to assume what attributes you apply to the element, what xsd you want to use, etc. I think it makes much more sense for a user to actually define the entirety of the HTML.

dcarbone avatar Jul 20 '17 15:07 dcarbone

Okay, sounds logical. From the specification I see that an optional lang attribute can also be added to the div element so that is possible this way. Thanks, I think this issue can be resolved.

leonrenkema avatar Jul 21 '17 07:07 leonrenkema

It looks like this fix is reverted, we are seeing htmlencoded xml inside the <div> when serializing to XML. The JSON looks good.

leonrenkema avatar Aug 26 '20 12:08 leonrenkema

@leonkrema thanks for reporting this. one question: are you pulling from master? if so, i am in the process of replacing SimpleXML with DOMDocument for xml manipulation, and it is not quite finished yet.

I unfortunately won’t have time to continue work on this until later in the week, so for the moment it may be better to use the latest tagged version.

dcarbone avatar Aug 26 '20 13:08 dcarbone

@leonrenkrema sorry used my phone to comment, got your name wrong :/

dcarbone avatar Aug 26 '20 13:08 dcarbone

@leonrenkema I'm not sure if you're still using this package, but I have updated master with a version that should address this for you.

If you could, please give it a try and let me know if it addresses the issue for you.

dcarbone avatar Oct 30 '22 02:10 dcarbone

Hi,

I have tested it against the latest master and the R4 specs. But it is not working as expected.

$narrative = new FHIRNarrative([
     'div' => new FHIRXHTML('This is a simple example with only plain text')
]);

This is what I am getting.

<div>
   <html>
     <body>
        <p>This is a simple example with only plain text</p>
     </body>
   </html>
</div>

The json variant looks like this

{"div":"<html><body><p>This is a simple example with only plain text<\/p><\/body><\/html>"}

To be honest I do not get where the <body> and <html> tags come from.

For comparison when I generate the same xml with the C# library it produces the output like this:

var narrative = new Narrative();
narrative.Div = "This is a simple example with only plain text";
var serializer = new FhirXmlSerializer();
var xmlText = serializer.SerializeToString(narrative);
Console.WriteLine(xmlText);
<Narrative xmlns="http://hl7.org/fhir">
   <div xmlns="http://www.w3.org/1999/xhtml">This is a simple example with only plain text</div>
</Narrative>

This is the output that I should expect.

leonrenkema avatar Nov 03 '22 10:11 leonrenkema

oh very weird...alright, i'll take a look at that. that xml type was written fairly quickly, so I'm sure i messed something up somewhere.

dcarbone avatar Nov 03 '22 14:11 dcarbone

This has been addressed by #100 will (finally) close once v3 reaches release

dcarbone avatar Apr 30 '24 15:04 dcarbone

@leonrenkema: I have release v3.0.0 that allows you to specify an arbitrary HTML value for the Narrative div. Can you please try it out, see if it addresses this issue for you?

dcarbone avatar May 03 '24 21:05 dcarbone