Reputation: 21
I need to write a XSLT to get the value of the nearest dictionary value to a give node. For example, my structure could be as below
<rootnode>
<rootcontainer>
<dictionary>
<key1> value /<key1>
</dictionary>
<pages>
<page1>
<!--xslt goes here-->
</page1>
</pages>
</rootcontainer>
<dictionary>
<key1>
independent value
</key1>
<key2>
value 2
</key2>
</dictionary>
</rootnode>
I want to create variables $key1
and $key2
inside page1
. The value of $key1
will be "value" and the value of $key2
will be "value 2". If rootcontainer\dictionary\key1
doesn't exist, the value of $key1
will be "independent value".
I hope this makes sense.
Upvotes: 2
Views: 592
Reputation: 243479
Here is a compact way to define the required variables:
<xsl:variable name="vKey1" select=
"(/*/rootcontainer/dictionary/key1
|
/*/dictionary/key1
)
[1]
"/>
<xsl:variable name="vKey2" select=
"(/*/rootcontainer/dictionary/key2
|
/*/dictionary/key2
)
[1]
"/>
When wrapped in a simple xslt stylesheet:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:variable name="vKey1" select=
"(/*/rootcontainer/dictionary/key1
|
/*/dictionary/key1
)
[1]
"/>
<xsl:variable name="vKey2" select=
"(/*/rootcontainer/dictionary/key2
|
/*/dictionary/key2
)
[1]
"/>
<xsl:template match="/">
Key1: <xsl:value-of select="$vKey1"/>
Key2: <xsl:value-of select="$vKey2"/>
</xsl:template>
</xsl:stylesheet>
and applied on the provided XML document (corrected, as it was severely malformed):
<rootnode>
<rootcontainer>
<dictionary>
<key1> value </key1>
</dictionary>
<pages>
<page1> </page1>
</pages>
</rootcontainer>
<dictionary>
<key1> independent value </key1>
<key2> value 2 </key2>
</dictionary>
</rootnode>
the wanted, correct result is produced:
Key1: value
Key2: value 2
Explanation:
The expression:
(/*/rootcontainer/dictionary/key1
|
/*/dictionary/key1
)
[1]
means:
Take the nodeset of (potentially) the two elements and from them take the first one in document order.
Because, the second of these two elements comes later in document order, it will be the first (and selected), only when the first of the two XPath expressions surrounding the union ( |
) operator, doesn't select any element.
Upvotes: 2
Reputation: 49764
I'm not sure I understand the question but you can assign a conditional value to a variable in two ways:
<xsl:choose>
<xsl:when test="your test condition">
<xsl:variable name="key1" select="your value">
</xsl:when>
<xsl:otherwise>
<xsl:variable name="key1" select="your alternative value">
</xsl:otherwise>
</xsl:choose>
Or more succintly:
<xsl:variable name="key1" select="if(your test condition) then your value else your alternative value;"/>
Update: Thanks for the update of the question. I'll give it a go now.
<xsl:template match="page1">
<xsl:choose>
<xsl:when test="../../preceding-sibling:dictionary[1]/key1">
<xsl:variable name="key1" select="../../preceding-sibling:dictionary[1]/key1">
</xsl:when>
<xsl:otherwise>
<xsl:variable name="key1" select="../../../following-sibling:dictionary[1]/key1">
</xsl:otherwise>
</xsl:choose>
</xsl:template>
So the value of $key1
will be the <key1>
node in the preceding dictionary if there is one, and the <key1>
node in the following dictionary if there isn't. Is that correct?
(You can use the if/then/else
structure too if you want to, but I used xsl:choose
because it's probably easier to read.)
Upvotes: 0