Reputation: 388
I have an xml schema with an element defined of type xs:boolean like this:
<xs:element name="useful"
minOccurs="1" maxOccurs="1"
type="xs:boolean"/>
I'm trying to use a choose/when/otherwise block in XSL to output something specific based on the value of that, like this:
<xsl:choose>
<xsl:when test="@useful = 0">No</xsl:when>
<xsl:otherwise>Yes</xsl:otherwise>
</xsl:choose>
I've tried every variation I can think of for that comparison (using true(), false(), 1, 0, removing the @, using //@) and it always prints out 'Yes'. What am I doing wrong here?
EDIT (by request from Martin Honnen):
Here's a sample of XML that's being used:
<?xml version="1.0"?>
<functions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="functions.xsd">
<function>
<name>func1</name>
<useful>0</useful>
</function>
<function>
<name>func2</name>
<useful>1</useful>
</function>
</functions>
This causes problems with using xsl:template I think, so I'm using xsl:for-each to loop through each function, and trying to output something specific for each useful tag. xsl:template can only be used at the top level of the xslt, correct?
The full XSLT file is
<?xml version='1.0' ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html><body>
<h2>Functions</h2>
<table border="1">
<tr>
<th>Functions</th>
<th>Useful</th>
</tr>
<xsl:for-each select="functions/function">
<tr>
<td>
<xsl:value-of select="name"/>
</td>
<td>
<xsl:choose>
<xsl:when test="@useful = 0">No</xsl:when>
<xsl:otherwise>Yes</xsl:otherwise>
</xsl:choose>
</td>
</tr>
</xsl:for-each>
</table>
</body></html>
</xsl:template>
</xsl:stylesheet>
Upvotes: 2
Views: 6539
Reputation: 243579
I think the schema defines an element, but you are testing the value of an attribute -- this may be your main problem.
<xsl:choose>
<xsl:when test="@useful = 0">No</xsl:when>
<xsl:otherwise>Yes</xsl:otherwise>
</xsl:choose>
I've tried every variation I can think of for that comparison (using
true()
,false()
,1
,0
, removing the@
, using//@
) and it always prints out 'Yes'. What am I doing wrong here?
Most probably the current node is not an element that has an attribute named useful
.
Here is how to work in XSLT 1.0 with the useful
element type as defined by the schema:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="useful/text()[. = 'true' or .='1']">
Yes
</xsl:template>
<xsl:template match="useful/text()[. = 'false' or .='0']">
No
</xsl:template>
</xsl:stylesheet>
when this transformation is applied to the following XML document:
<t>
<useful>true</useful>
<useful>false</useful>
<useful>1</useful>
<useful>0</useful>
</t>
the wanted, correct result is produced:
<t>
<useful>
Yes
</useful>
<useful>
No
</useful>
<useful>
Yes
</useful>
<useful>
No
</useful>
</t>
In XSLT 2.0 (Schema-aware processor), you need to import the schema (use <xsl:import-schema>
) then you can simply use:
('no', 'yes')[number(useful)+1]
where the current node is the parent of the useful
element.
Upvotes: 3
Reputation: 167716
Your schema defines an element named "useful" but the schema is not relevant at all unless you are trying to use schema aware XSLT 2.0.
Doing @useful
in XPath selects an attribute of that name of the context node which does not make any sense with the schema you have, as that defines an element.
So show us your instance XML the XSLT is processing, then we can show you some XSLT code:
<xsl:template match="useful">
<xsl:choose>
<xsl:when test=". = 'false' or . = 0">No</xsl:when>
<xsl:otherwise>Yes</xsl:otherwise>
</xsl:choose>
</xsl:template>
With schema-aware XSLT 2.0 you could do
<xsl:template match="useful">
<xsl:value-of select="if (data(.)) then 'Yes' else 'No'"/>
</xsl:template>
Upvotes: 1