Reputation: 10207
I wonder if there's a way in XSLT to modify / add to an attribute value.
Right now I am simply replacing the attribute value:
<a class="project" href="#">
<xsl:if test="new = 'Yes'">
<xsl:attribute name="class">project new</xsl:attribute>
</xsl:if>
</a>
But I don't like the repetition of project
in line 2. Is there a better way to do this, e.g. to simply add new
at the end of the attribute?
Thanks for any help!
Upvotes: 2
Views: 191
Reputation: 243459
In XSLT 1.0 one can use this one-liner:
<a class="project{substring(' new', 5 - 4*(new = 'Yes'))}"/>
Here is a complete transformation:
<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="/*">
<a class="project{substring(' new', 5 - 4*(new = 'Yes'))}"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the following XML document:
<t>
<new>Yes</new>
</t>
the wanted, correct result is produced:
<a class="project new"/>
Explanation:
Use of AVT (Attribute Value Templates)
To select a string based on condition, in XPath 1.0 one can use the substring function and specify as the starting-index argument an expression, which evaluates to 1 when the condition is true()
and to some number that is greater than the length of the string -- otherwize.
We use the fact that in XPath 1.0 any argument of the *
(multiplication) operator is converted to a number, and that number(true()) = 1
and number(false()) = 0
II. XSLT 2.0 solution:
Use this one-liner:
<a class="project{(' new', '')[current()/new = 'Yes']}"/>
Here is a complete transformation:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<a class="project{(' new', '')[current()/new = 'Yes']}"/>
</xsl:template>
</xsl:stylesheet>
When applied on the same XML document (above), again the same wanted, correct result is produced:
<a class="project new"/>
Explanation:
Upvotes: 0
Reputation: 122364
You can put the if
inside the attribute
instead of the other way round:
<a href="#">
<xsl:attribute name="class">
<xsl:text>project</xsl:text>
<xsl:if test="new = 'Yes'">
<xsl:text> new</xsl:text>
</xsl:if>
</xsl:attribute>
</a>
An <xsl:attribute>
can contain any valid XSLT template (including for-each
loops, applying other templates, etc.), the only restriction being that instantiating this template must only generate text nodes, not elements, attributes, etc. The attribute value will be the concatenation of all these text nodes.
Upvotes: 3