tags:

views:

408

answers:

2

This is probably a really easy answer, but for the life of me I can't figure it out.

I want to display certain content depending on which child element is being displayed but I don't know how to test for the element I want. I want to see if the start, stop, and note elements exist

<xsl:template match="protocol[@id=$protocolNumber]">
<h4><xsl:value-of select="$sectionNumber"/>.<xsl:value-of select="@id"/>&nbsp;<xsl:value-of select="@title"/></h4>
<p>
     <xsl:for-each select="child::*"> 
        <xsl:choose>
            <xsl:when test="start">
                <span id="start"><xsl:value-of select="start[@level]" /></span>
            </xsl:when>
            <xsl:when test="stop">
                <span id="stop"><xsl:value-of select="stop[@level]" /></span>
            </xsl:when>
            <xsl:when test="note">
                <span id="note"><xsl:value-of select="note[@title]" />:&nbsp;<xsl:value-of select="note/text()" /></span>
            </xsl:when>
            <xsl:otherwise>
             <xsl:value-of select="text()"/><br/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:for-each>
</p>

<protocol id="2" title="Post-Conversion Of VF / VT">
   <note title="criteria">Post-conversion treatment of VF or VT should only be started if the patient has regained a pulse of adequate rate, and has a supraventricular rhythm.  If not, refer to other cardiac protocols as appropriate.  All antiarrhythmics are  contraindicated if ventricular escape rhythm is present.</note>
   <start level="All Levels"/>
   <step>Routine medical care.</step>
   <stop level="EMT"/>
   <stop level="EMT-I"/>
   <start level="EMT-CC &amp; P"/>
   <step>
    If conversion results from defibrillation without any drug therapy:<br/><br/>
    Amiodarone (Cordarone) 150 mg IV/IO Slow IV
   </step>
   <step>If Amiodarone was the drug resulting in conversion from VF/VT, no additional antiarrhythmic is required.</step>
   <step>
    If Lidocaine (Xylocaine) was the drug resulting in conversion from VF/VT:<br/><br/>
    Repeat Lidocaine bolus 0.75 mg/kg IV/IO every 10 minutes up to a total cumulative dose of 3 mg/kg.
   </step>
   <step>If more than above listed doses are needed because of length of transport time, contact Medical Control.</step>
  </protocol>
+1  A: 

I'm not sure what you're trying to do, but I see a few likely problems:

First, you use <xsl:choose /> construct, which means that if you have "start" no "stop" and "note" will be handled (you may want to use plain <xsl:if />s instead, or whatever the desired logic suggests.

Second, when you use start@level, I believe you really mean start/@level.

Michael Krelin - hacker
I actually meant start[@level], but either way it was wrong the first time. Thanks.I have a for loop so I'm assuming that for each iteration, it will loop through and choose if it's start, do one thing. If it's stop, do another, etc. Is that correct?
cfree
Ahh.. I haven't really read your code carefully. It looks like what you're getting at is `test="local-name()='start'"` and similar. But Pavel pointed you to more common way to do it.
Michael Krelin - hacker
+5  A: 

Inside xsl:for-each, the context element . is the current element you're iterating over. When you write an XPath expression like start, it really is the same as child::start. What you want here is self::start. Also note that child::* is redundant - just * will do.

A more idiomatic XSLT approach is to refactor this into a separate set of templates, and let pattern matching do its job:

<xsl:template match="protocol[@id=$protocolNumber]">
  <h4><xsl:value-of select="$sectionNumber"/>.<xsl:value-of select="@id"/>&nbsp;<xsl:value-of select="@title"/></h4>
  <p>
    <!-- Applies templates to all child elements -->
    <xsl:apply-templates/>
  </p>
</xsl:template>

<xsl:template match="protocol/start">
  <span id="start"><xsl:value-of select="start/@level" /></span>
</xsl:template>

<xsl:template match="protocol/stop">
  <span id="stop"><xsl:value-of select="stop/@level" /></span>
</xsl:template>

<xsl:template match="protocol/note">
  <span id="note"><xsl:value-of select="note/@title" />:&nbsp;<xsl:value-of select="note" /></span>
</xsl:template>

<xsl:template match="protocol/*">
   <xsl:value-of select="."/>
</xsl:template>
Pavel Minaev
+1, but presence of non $protocolNumber protocol elements worries me.
Michael Krelin - hacker
Very nice, that makes much more sense. Thanks!
cfree