Specific order for XSL Template output

2019-08-29 13:05发布

问题:

I've got the following xml file:

<section>
  <templateId root="2.16.840.1.113883.10.20.22.2.4" />
  <text>
    <list listType="ordered">
      <item>9/18/2013 - Weight - 125 lbs</item>
      <item>9/18/2013 - Blood Pressure - 120/80 mm Hg</item>
      <item>9/18/2013 - BMI - 19 98</item>
      <item>9/11/2013 - Weight - 125 lbs</item>
      <item>9/11/2013 - Blood Pressure - 120/80 mm Hg</item>
      <item>9/11/2013 - BMI - 19 98</item>
      <item>9/11/2013 - Pulse - 32</item>
    </list>
  </text>
</section>

I have the following xsl template information:

<xsl:key name="vs_times" match="//hl7:section[hl7:templateId/@root='2.16.840.1.113883.10.20.22.2.4']/hl7:text/hl7:list/hl7:item" use="substring-before(., ' - ')"/>

    <xsl:template match="hl7:section[hl7:templateId/@root='2.16.840.1.113883.10.20.22.2.4']">
    <div style="padding: 5px; border-top: 1px solid #000000;">
        <span style="font-weight: bold;">Vital Signs: </span>
        <br/>
        <table border="0" cellspacing="0" cellpadding="1" width="100%">
            <xsl:apply-templates select="hl7:text/hl7:list/hl7:item[generate-id(.)=generate-id(key('vs_times', substring-before(., ' - ')))]" mode="group" />
        </table>
    </div>
</xsl:template>
<xsl:template match="hl7:item" mode="group">
    <tr>
        <td style="width: 76px;">
            <xsl:value-of select="substring-before(., ' - ')" />
        </td>
        <xsl:variable name="values" select="key('vs_times', substring-before(., ' - '))"/>
        <xsl:apply-templates select="$values" />
    </tr>
</xsl:template>
<xsl:template match="hl7:item">
    <td style="width: 180px; padding-left: 3px;">
        <xsl:apply-templates select="." mode="content" />
    </td>
</xsl:template>
<xsl:template match="hl7:item[contains(., 'Blood Pressure')]" mode="content">
    <span style="font-weight: bold;">Blood Pressure: </span>
    <xsl:value-of select="substring-before(substring-after(., 'Blood Pressure - '), ' ')"/>
</xsl:template>
<xsl:template match="hl7:item[contains(., 'Pulse')]" mode="content">
    <span style="font-weight: bold;">Pulse: </span>
    <xsl:value-of select="substring-before(substring-after(., 'Pulse - '), ' ')"/>
</xsl:template>
<xsl:template match="hl7:item[contains(., 'Weight')]" mode="content">
    <span style="font-weight: bold;">Weight: </span>
    <xsl:value-of select="substring-after(., 'Weight - ')"/>
</xsl:template>
<xsl:template match="hl7:item[contains(., 'BMI')]" mode="content">
    <span style="font-weight: bold;">BMI: </span>
    <xsl:value-of select="substring-before(substring-after(., 'BMI - '), ' ')"/>
</xsl:template>
<xsl:template match="hl7:item" mode="content">
    &#xa0;
</xsl:template>

This outputs the information but I need the output to be in a different order (potentially) than the items being iterated through. I need them to be the same order all the time:

  • Blood Pressure
  • Pulse
  • Weight
  • BMI

As of now, it's just looping through each item and outputting them as it comes to them.

Also, if there isn't one of the four items (as there is no pulse item in the first set of dates in the example) there needs to be a blank space. Finally, the second row needs to be an alternate color than the first row.

Thanks

回答1:

This is a bit tricky, but please give this a try. It turns out that this did seem like a good time to use choose/when but not in the manner you were planning to:

  <xsl:key name="vs_times" 
           match="hl7:section
                      [hl7:templateId/@root='2.16.840.1.113883.10.20.22.2.4']
                      /hl7:text/hl7:list/hl7:item" use="substring-before(., ' - ')"/>

  <xsl:template match="hl7:section
                         [hl7:templateId/@root='2.16.840.1.113883.10.20.22.2.4']">
    <div style="padding: 5px; border-top: 1px solid #000000;">
      <span style="font-weight: bold;">Vital Signs: </span>
      <br/>
      <table border="0" cellspacing="0" cellpadding="1" width="100%">
        <xsl:apply-templates
          select="hl7:text/hl7:list/hl7:item
                     [generate-id(.)=
                      generate-id(key('vs_times', 
                                  substring-before(., ' - ')))]"
          mode="group" />
      </table>
    </div>
  </xsl:template>
  <xsl:template match="hl7:item" mode="group">
    <tr>
      <td style="width: 76px;">
        <xsl:value-of select="substring-before(., ' - ')" />
      </td>
      <xsl:variable name="values"
                    select="key('vs_times', substring-before(., ' - '))"/>

      <xsl:call-template name="row">
        <xsl:with-param name="type" select="'Blood Pressure'" />
        <xsl:with-param name="values" select="$values" />
      </xsl:call-template>
      <xsl:call-template name="row">
        <xsl:with-param name="type" select="'Pulse'" />
        <xsl:with-param name="values" select="$values" />
      </xsl:call-template>
      <xsl:call-template name="row">
        <xsl:with-param name="type" select="'Weight'" />
        <xsl:with-param name="values" select="$values" />
      </xsl:call-template>
      <xsl:call-template name="row">
        <xsl:with-param name="type" select="'BMI'" />
        <xsl:with-param name="values" select="$values" />
      </xsl:call-template>
    </tr>
  </xsl:template>

  <xsl:template name="row">
    <xsl:param name="type" />
    <xsl:param name="values" select="/.." />

    <xsl:variable name="foundValue" select="$values[contains(., $type)]" />

    <td style="width: 180px; padding-left: 3px;">
      <xsl:if test="$type = 'Pulse' or $type = 'BMI'">
        <xsl:attribute name="class">alternate</xsl:attribute>
      </xsl:if>

      <xsl:choose>
        <xsl:when test="$foundValue">
          <span style="font-weight: bold;">
            <xsl:value-of select="concat($type, ': ')" />
          </span>
          <xsl:value-of select="substring-after($foundValue, concat($type, ' - '))"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:text>&#xa0;</xsl:text>
        </xsl:otherwise>
      </xsl:choose>
    </td>
  </xsl:template>