Reputation: 193
I want to get first non-empty value of two and put it to "value" attribute of a text input. So, I do:
<input type="text">
<xsl:attribute name="value">
<xsl:choose>
<xsl:when test="some/@attr != ''">
<xsl:value-of select="some/@attr" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="some/another/@attr" /> <!-- always non-empty, so get it -->
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</input>
Question is: is there a way to make it with less lines of code?.. Maybe, like that: <input type="text" value="some/@attr or some/another/@attr" />
or something?.. Like in, say, Perl: my $val = 0 || 5;
Thanks in advance for your help
UPD XSLT 1.0
Upvotes: 3
Views: 1565
Reputation: 243459
Even the union can be avoided:
<input type="text"
value="{some/@attr[string(.)]}{some[not(string(@attr))]/another/@attr}">
</input>
Here we also avoid the precedence dependence of the two attributes that is common to all other given answers -- we don't suppose that the first attribute precedes the second attribute in document order.
We could write this equivalent code, reversing the order of the two AVTs:
<input type="text"
value="{some[not(string(@attr))]/another/@attr}{some/@attr[string(.)]}">
</input>
Upvotes: 3
Reputation: 9627
The relay magic is already in the answer form @Martin Honnen. As enhancement,to make it even a little shorter you can use "Attribute Value Templates"
<input type="text" value="{some/@attr[. != ''] | some/another/@attr}">
</input>
Upvotes: 1
Reputation: 167571
If you use
<xsl:attribute name="value">
<xsl:value-of select="some/@attr[. != ''] | some/another/@attr"/>
</xsl:attribute>
then with XSLT 1.0 value-of
semantics the string value of the first node selected by some/@attr[. != ''] | some/another/@attr
is output. Thus if some/@attr[. != '']
selects a node it should be output, otherwise some/another/@attr
(as I think some/@attr
is considered preceding some/child-element/@attr
in document order).
Upvotes: 6