Technocrat Aspire
Technocrat Aspire

Reputation: 21

Conditional Sibling Value

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

Answers (2)

Dimitre Novatchev
Dimitre Novatchev

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

biziclop
biziclop

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

Related Questions