I want to use the attribute @sourcename
in the following way, as a convenience:
If @sourcename
has a dot in it, the part before the first dot should be assigned to $srcgroup
and the part after the first dot should be assigned to $srcword
.
Otherwise $srcgroup
should be set equal to @sourcename
and $srcword
should be the empty string.
In both cases I want to do the same things using $srcgroup
and $srcword
.
I tried this with the following fragment:
<xsl:choose>
<xsl:when test="contains(@sourcename, '.')">
<xsl:variable name="srcgroup" select="substring-before(@sourcename, '.')"/>
<xsl:variable name="srcword" select="substring-after(@sourcename, '.')" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="srcgroup" select="@sourcename" />
<xsl:variable name="srcword" />
</xsl:otherwise>
</xsl:choose>
<foo group="{$srcgroup}" word="{$srcword}" />
<!-- there's some other more complicated users of $srcgroup and $srcword -->
The problem is I get an error (this is using JAXP in Java):
ERROR: [my xsl file]: line 35: Variable or parameter 'srcgroup' is undefined.'
FATAL ERROR: 'Could not compile stylesheet'
Exception in thread "main" javax.xml.transform.TransformerConfigurationException: Could not compile stylesheet
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTemplates(TransformerFactoryImpl.java:825)
If I understand this right, I'm guessing the variables only have the scope of the particular case in the <xsl:choose>
block. Is there any way to get around this? I don't want to have to repeat my other code twice.
p.s. I found a workaround:
<xsl:variable name="srcgroup" select="substring-before(concat(@sourcename, '.'), '.')" />
<xsl:variable name="srcword" select="substring-after(@sourcename, '.')" />
but I still want to know how to solve my original question, for future reference.
Just use (no conditionals necessary):
<xsl:variable name="srcgroup" select=
"substring-before(concat(@sourcename, '.'), '.')"/>
<xsl:variable name="srcword" select=
"substring-after(@sourcename, '.')"/>
Complete example:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="x|y">
<xsl:variable name="srcgroup" select=
"substring-before(concat(@sourcename, '.'), '.')"/>
<xsl:variable name="srcword" select=
"substring-after(@sourcename, '.')"/>
$srcgroup = "<xsl:value-of select="$srcgroup"/>"
$srcword = "<xsl:value-of select="$srcword"/>"
</xsl:template>
</xsl:stylesheet>
when applied on this XML document:
<t>
<x sourcename="a.b.c"/>
<y sourcename="noDots"/>
</t>
the wanted result is produced in both cases:
$srcgroup = "a"
$srcword = "b.c"
$srcgroup = "noDots"
$srcword = ""
Explanation: Unnecessary logic avoided by placing a sentinel.
Compare this to the much more verbose conditional syntax:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="x|y">
<xsl:variable name="srcgroup">
<xsl:choose>
<xsl:when test="contains(@sourcename, '.')">
<xsl:value-of select="substring-before(@sourcename, '.')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@sourcename"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="srcword">
<xsl:choose>
<xsl:when test="contains(@sourcename, '.')">
<xsl:value-of select="substring-after(@sourcename, '.')"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
$srcgroup = "<xsl:value-of select="$srcgroup"/>"
$srcword = "<xsl:value-of select="$srcword"/>"
</xsl:template>
</xsl:stylesheet>
When this more verbose transformation is applied on the same XML document (above), again the same correct result is produced:
$srcgroup = "a"
$srcword = "b.c"
$srcgroup = "noDots"
$srcword = ""
It's more like this:
<xsl:variable name="srcgroup">
<xsl:choose...>
...
</xsl:choose>
</xsl:variable>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With