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.
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>
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.
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
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
<xsl:choose>
is invoked. The testrow[@respondentabn='']
is looking for the existence of arow
withrespondentabn
equal to a zero length string. If applied withCourseData
as the context node it is true because there exists one such row - Jim Garrison 2012-04-03 23:09