XML: define variable in an optimal way

Viewed 95

From same input I have different xpaths for the same element (its almost exactly the same path except for 1 element, see below)

My logic its depends on the element "typology" (defined on my code)

XSLT 1.0

<xsl:variable name="date">
<xsl:choose>
<xsl:when test="$typology='A' or $typology='B' ">
<xsl:value-of select="/Header/info/data/Body/basketAB/date"/>
</xsl:when>
<xsl:when test="$typology='C' or $typology='D' or $typology='E'">
<xsl:value-of select="/Header/info/data/Body/basketCDE/date"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'CheckPath'"/>
</xsl:otherwise>
</xsl:choose>

How can I avoid to use choose +several paths and get "date" just from 1 path.

3 Answers

Solve it defining date as:

<xsl:variable name="date" select="//date"/>

I would avoid the descendant axis and use a more explicit path:

<xsl:variable name="date" select="/Header/info/data/Body/*/date"/>

This is assuming that the input cannot contain both basketAB and basketCDE elements (this point is not clear from your question, but otherwise neither this nor the currently accepted answer can work).


If the above assumption turns out to be incorrect, you could do:

<xsl:variable name="date" select="/Header/info/data/Body/*[contains(name(), $typology)]/date"/>

Use this single XPath 1.0 expression:

concat(/Header/info/data/Body/basketAB
                               [contains('|A|B|', concat('|', $typology, '|'))]/date
     | /Header/info/data/Body/basketCDE
                              [contains('|C|D|E|', concat('|', $typology, '|'))]/date,
       substring('CheckPath', 
                 1 div not(contains('|A|B|C|D|E|', concat('|', $typology, '|'))))
      )

Verification using XSLT 1.0:

Given this source XML document:

<Header>
  <info>
    <data>
        <Body>
          <basketAB>
             <date>date1</date>
          </basketAB>
          <basketCDE>
             <date>date2</date>
          </basketCDE>
        </Body>
    </data>
  </info>
</Header>

this XSLT transformation evaluates the above XPath expression and outputs the result of this evaluation:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:variable name="typology" select="'A'"/>

  <xsl:template match="/">
    <xsl:variable name="date" select=
      "concat(/Header/info/data/Body/basketAB[contains('|A|B|', concat('|', $typology, '|'))]/date
            | /Header/info/data/Body/basketCDE[contains('|C|D|E|', concat('|', $typology, '|'))]/date,
              substring('CheckPath', 1 div not(contains('|A|B|C|D|E|', concat('|', $typology, '|'))))
              )"/>
    <xsl:value-of select="$date"/>
  </xsl:template>
</xsl:stylesheet>

Run the transformation several times, each time specifying a different value for the variable $typology:

The wanted results are produced in all cases:

'A' --> date1

'B' --> date1


'C' --> date2

'D' --> date2

'E' --> date2


'X' --> CheckPath

Related