Convert your FHIR JSON -> XML and back here. The CDA Book is sometimes listed for Kindle here and it is also SHIPPING from Amazon! See here for Errata.

Thursday, January 26, 2012

The XSLT document() function

Yesterday, someone asked a question about how to address issues of translating a code to a display name on one of the the Structured Documents workgroup's e-mail lists.  There's a technique that I've been using in XSLT for quite some time that allows me to access look-up tables very easily without having to embed translation logic in the XSLT stylesheet.  Before I describe the technique, I thought I'd share some of the various uses for it:
  1. Code translation.  Often you will have codes in a one code system that need to be translated into codes from another code system.  This technique allows you to look up the translation.  I've used this to translate local codes to codes from standard vocabularies for:
    1. Unit translation from ANSI+ to UCUM
    2. Local codes for problem severity to SNOMED codes for severity used in the HITSP C32
    3. Local codes for problem status to SNOMED codes for problem status.
    4. Local codes for problem type to SNOMED codes for problem type.
    5. Local codes for vital signs to LOINC codes for vital signs.
  2. Display name lookup.  Closely related to #1 above.  Often times, I have a standard code, but not the display name associated with it.  I can use this technique on small value sets (less that 1000 codes) to look up the display name (this is the use case for the problem presented on the list).
  3. Mapping from an identifier to a web service end point.  You can use this technique to map from:
    1. The home community ID to an XCA Web Service address
    2. A DICOM AE Title to a WADO Web Service endpoint.
  4. Validating against a dynamically changing rule, such as the validation of a code element against the current version of a vocabulary or value set.
The basic technique is to create (or have access to) an XML document resource which you will use in your stylesheet.  To declare this resource, you do something like the following:

<xsl:variable name="myDocument" select="document('mydocument.xml')"/>

This creates a variable which can be used in an XPath expression subsequently in your XML.  In the use case the querant posed, the issue was how to get a display name for a language code, to that the patients preferred language (expressed as a code) could be displayed in the UI.  The patient's language preferences are stored in the patient/languageCommunication/languageCode/@code attribute.

The following XSLT fragment shows a template that will return the display name of the patient language by looking it up through an XML document.

<xsl:variable name="langs" select="document('lang.xml')"/>
<xsl:template name='patientLanguage'>
  <!-- get the code -->
  <xsl:variable name='lang'
  <xsl:variable name='mappedLang' select='$langs//language[@code=$lang]'/>
    <xsl:when test='$mappedLang'>
      <xsl:value-of select='$mappedLang/@displayName'/>

The same technique can also be used to access a resource that is created dynamically through a RESTful web-server end-point.  I demonstrate one use of this technique in the post on Values Sets and Query Health.  

Another use for this technique is to check value-set conformance inside Schematron rules. If you have a requirement that code/@code come from a particular value set, you can write a rule that accesses a web resource based on the value set, as in the following example:

<rule context='*/cda:templateId[@root = templateIdentifier]'>
  <let name='code' value='cda:code/@code'/>
  <let name='valueSetDoc' value='document("")'/>
  <assert test='$valueSetDoc//ihe:Concept[@code = $code]'>
    The code/@code element must come from the XXX Value Set (OID: 1.2.840.10008.6.1.308)

The use of external XML data files is a very powerful feature of XSLT.  Combining that use with dynamically created XML resources through web services makes it even more capable.

1 comment:

  1. Hi, where can I get a copy of the xsl file . The one I'm having doesn't include a template for "patientLanguage"