xsl:when not working as expected

Go To StackoverFlow.com

0

I have a table that is populated from a SQL database. Most of the data entered will have an ABN which I can use to look up email and name. Some data doesn't have an ABN, and only has a UID. I don't want to have to display the UID in the table since its unnecessary 98% of the time, so I want to use an xsl:when to change the name field to the UID if there isn't a name.

Here is an example of the 2 cases in XML:

    <?xml version="1.0" encoding="UTF-8"?>
    <CourseData>
      <row batchid="0" courseid="10101" createdon="04/03/2012 01:08PM" datecompleted="1:08 PM" datecompletedDateValue="1333483680000" lastupdatebyabn="999999" lastupdatebyuid="tsmith" lastupdateon="04/03/2012 01:08PM" num="2" respondentabn="999999" respondentemail="tsmith@test.com" respondentid="1" respondentname="Thomas Smith" respondentuid="tsmith"/>       
      <row batchid="0" courseid="10101" createdon="04/03/2012 01:08PM" datecompleted="1:08 PM" datecompletedDateValue="1333483697000" lastupdatebyabn="" lastupdatebyuid="jsmith" lastupdateon="04/03/2012 01:08PM" num="3" respondentabn="" respondentemail="" respondentid="2" respondentname=" " respondentuid="jsmith"/>
    </CourseData>

Here is the XSL I'm using, which obviously isn't working.

    <xsl:choose>
      <xsl:when test="row[@respondentabn='']">
        <label datafield="@respondentuid"></label>
      </xsl:when>
      <xsl:otherwise>
        <label datafield="@respondentname"></label>
      </xsl:otherwise></xsl:choose></td>

How can I fix this?

Edit: So after talking to my boss, he said for one I'd need an loop in there for this to work right, but that I really shouldn't be doing this in the .xsl anyways. I modified my sql that is serving up the data to make that change for me, which in retrospect, I probably should have thought of in the first place.

2012-04-03 21:55
by Corwin01
Please show some expected output and more of the XSL showing the context in which this <xsl:choose> is invoked. The test row[@respondentabn=''] is looking for the existence of a row with respondentabn equal to a zero length string. If applied with CourseData as the context node it is true because there exists one such row - Jim Garrison 2012-04-03 23:09


0

You don't give much indication of the stylesheet so it's hard to be sure but I'd guess you have something like

<xsl:for-each select="row">
<xsl:choose>
      <xsl:when test="row[@respondentabn='']">
        <label datafield="@respondentuid"></label>
      </xsl:when>
      <xsl:otherwise>
        <label datafield="@respondentname"></label>
      </xsl:otherwise>
</xsl:choose>
</xsl:for-each>

or in any event if the current node is such that row[@respondentabn=''] does anything useful it must be the parent of row in which case <label datafield="@respondentuid"> would select attributes of the parent (even if the AVT syntax was corrected).

So I would guess:

<xsl:for-each select="row">
<xsl:choose>
      <xsl:when test="string(@respondentabn)">
        <label datafield="{@respondentuid}"></label>
      </xsl:when>
      <xsl:otherwise>
        <label datafield="{@respondentname}"></label>
      </xsl:otherwise>
</xsl:choose>
</xsl:for-each>

Or, more tersely

<xsl:for-each select="row">
   <label datafield="{@respondentuid[string(.)]|
                      @respondentname[not(string(../@respondentuid))]}"/>
 </xsl:for-each>
2012-04-04 00:24
by David Carlisle


0

With XSLT, you cannot check for the presence of an empty string in the strict sense. the easiest way to do this then is to evaluate the inverse:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

    <xsl:template match="/">
        <doc>   
           <xsl:apply-templates select="CourseData/row"/>   
        </doc>
    </xsl:template>

    <xsl:template match="CourseData/row"> 
        <xsl:choose>
            <xsl:when test="@respondentabn!=''"> 
                <xsl:element name="label">
                    <xsl:attribute name="datafield">
                       <xsl:value-of select="@respondentname"></xsl:value-of>   
                    </xsl:attribute>
                </xsl:element>
            </xsl:when>
            <xsl:otherwise>
                <xsl:element name="label">
                    <xsl:attribute name="datafield">
                        <xsl:value-of select="@respondentuid"></xsl:value-of>
                    </xsl:attribute>
                </xsl:element>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template> 

</xsl:stylesheet>

produces:

<doc><label datafield="Thomas Smith" /><label datafield="jsmith" /></doc>

Another approach would be to assign the value of the respondentabn attribute to a variable, you could then evaluate the when clause against the variable instead:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

    <xsl:template match="/">
        <doc>   
           <xsl:apply-templates select="CourseData/row"/>   
        </doc>
    </xsl:template>

    <xsl:template match="CourseData/row"> 
        <xsl:variable name="respondentabn">
           <xsl:value-of select="@respondentabn"/>
        </xsl:variable>

        <xsl:choose>
          <xsl:when test="$respondentabn=''">
            <xsl:element name="label">
               <xsl:attribute name="datafield">
                  <xsl:value-of select="@respondentuid"/>
               </xsl:attribute>
            </xsl:element>
          </xsl:when>
          <xsl:otherwise>
            <xsl:element name="label">
               <xsl:attribute name="datafield">
                  <xsl:value-of select="@respondentname"/>
               </xsl:attribute>
            </xsl:element>
          </xsl:otherwise>
        </xsl:choose>

    </xsl:template> 

</xsl:stylesheet>

produces:

<doc><label datafield="Thomas Smith" /><label datafield="jsmith" /></doc>

Both approaches will do what you need, its just a matter of which one is more understandable for you.

2012-04-03 22:08
by javram
I'm assuming that you didn't mean to leave in in the second example.

If so, both cases aren't working for me, and they stop leave the name blank for the case where we already have the name and ABN - Corwin01 2012-04-03 22:26

the two versions you show are not equivalent row[@respondentabn!=''] selects rows that have a respondentabn attribute that is not empty, but don't select rows with no such attribute. $respondentabn='' as written is true if any row has a non empty attribute of that name, but even if corrected to only select the current row, it would be true for the attribute having emoty value or the attribute being missing - David Carlisle 2012-04-04 00:19
For my own edification, I posted the full xslt for both of the original solutions I proposed. You should see that the output of both approaches is identical - javram 2012-04-04 01:48