Search code examples
xsltxsl-choose

xsl choose ignoring the when elements and only outputting the otherwise


I have an xslt template that i use for converting data, the one i have right now has a choose statement with a bunch of when clauses for each eventuality, the output given is that it seems to ignore all the when's and just goes straight to the otherwise.

ive removed a couple of when statements to shorten it

Ive been through it step by step, changed the select statement to look at the code=a directly.

Something is wrong with my when but i cant seem to see it

<xsl:for-each select="datafield[@tag='300']">               

<xsl:choose>                            
    <xsl:when test="./subfield[@code='a'] !='' and ./subfield[@code='e'] !='' and ./subfield[@code='c'] !=''">
        <xsl:element name="PhysicalDescription">
            <xsl:value-of select="./subfield[@code='a']" />
        </xsl:element>
        <xsl:element name="CoverColour">
            <xsl:value-of select="./subfield[@code='c']" /> - <xsl:value-of select="./subfield[@code='e']" />
        </xsl:element>
    </xsl:when>

    <xsl:when test="./subfield[@code='a'] !='' and ./subfield[@code='c'] !='' and ./subfield[@code='e'] =''">
        <xsl:element name="PhysicalDescription">
            <xsl:value-of select="./subfield[@code='a']" />
        </xsl:element>
        <xsl:element name="CoverColour">
            <xsl:value-of select="./subfield[@code='c']" />
        </xsl:element>
    </xsl:when>

    <xsl:otherwise>
        <xsl:element name="PhysicalDescription">
            <xsl:value-of select="./subfield[@code='a']" />
        </xsl:element>                               
   </xsl:otherwise>                 
</xsl:choose>

XML Data

    <datafield tag="300" ind1="0" ind2="0">
      <subfield code="a">1-914pp (vol.1)</subfield>
    </datafield>
    <datafield tag="300" ind1="0" ind2="0">
      <subfield code="a">915-2385pp (vol.2)</subfield>
    </datafield>
    <datafield tag="300" ind1="0" ind2="0">
      <subfield code="a">cli, 835p (supp)</subfield>
      <subfield code="e">Pbk</subfield>
    </datafield>
    <datafield tag="300" ind1="0" ind2="0">
      <subfield code="c">navy cover</subfield>
      <subfield code="e">Hbk</subfield>
    </datafield>

It should loop through the datafield[@tag='300'] node and for each one that it finds output a value based on the xsl:when.

it only ever outputs the otherwise statement


Solution

  • The problem you have is with expressions of this form....

    ./subfield[@code='e'] =''
    

    This will only be evaluated to try if a subfield[@code='e'] exists, and its value is an empty string. If there is no subfield[@code='e'] in your XML, then the expression evaluates to false.

    What you need to do is write it like this: (Note, the ./ prefix is not really needed in any of your expressions).

    not(subfield[@code='e'] !='')
    

    This is like a double-negative, but in the case subfield[@code='e'] does not exist, the expression now gets evaluated to true.

    So, for your given XSLT, instead of doing this:

    <xsl:when test="./subfield[@code='a'] !='' and ./subfield[@code='c'] !='' and ./subfield[@code='e'] =''">
    

    Do this

    <xsl:when test="subfield[@code='a'] !='' and subfield[@code='c'] !='' and not(subfield[@code='e'] !='')">
    

    Do note for your given XSLT, the xsl:when statements need both an "a" and "c" present in the XML, which is not the case for the sample provided.

    See http://xsltfiddle.liberty-development.net/ncntCRS as an example.