3

I need to get the xpath of current node for which i have written an xsl function

<func:function name="fn:getXpath">
    <xsl:variable name="xpath">
        <xsl:for-each select="ancestor-or-self::*">
            <xsl:value-of select="concat($xpath, name())" />
            <xsl:if test="not(position()=last())">
                <xsl:value-of select="concat('/', $xpath)" />
            </xsl:if>
        </xsl:for-each>
    </xsl:variable>
    <func:result select="$xpath" />
</func:function>

But when I run this, I'm getting the following error

file:///D:/test.xsl; Line #165; Column #63; Variable accessed before it is bound!
file:///D:/test.xsl; Line #165; Column #63; java.lang.NullPointerException

I'm using xalan 2.7.0. Please help.

Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265
rohit
  • 953
  • 5
  • 15
  • 31
  • Evem after fixing the obvious error, the produced expression would generally be in correct. Why? Because in the general case this XPath expression selects many elements -- not just one. – Dimitre Novatchev May 19 '12 at 19:16
  • You're going to run into problems anywhere you have two siblings with the same name- `` is going to give you an identical expression for both `` nodes. You should find a way of adding a `[1]`, `[2]`, etc., probably using the `position()` function or `preceding-sibling` axis. – Flynn1179 May 19 '12 at 21:30

2 Answers2

6

In your example you are trying to use the variable in the definition itself, which is not valid.

It looks your intention is to try and modify the value of an existing value. However XSLT is a functional language, and as a result variables are immutable. This means you cannot change the value once defined.

In this case, you don't need to be so complicated. You can just remove the reference to the variable itself, and you will get the result you need

<func:function name="fn:getXpath">
   <xsl:variable name="xpath">
      <xsl:for-each select="ancestor-or-self::*">
         <xsl:value-of select="name()"/>
         <xsl:if test="not(position()=last())">
            <xsl:value-of select="'/'"/>
         </xsl:if>
      </xsl:for-each>
   </xsl:variable>
   <func:result select="$xpath" />
</func:function> 
Tim C
  • 70,053
  • 14
  • 74
  • 93
2

You are using the variable $xpath inside the definition of the variable itself:

<func:function name="fn:getXpath">
    <xsl:variable name="xpath">  
        <xsl:for-each select="ancestor-or-self::*">
            <xsl:value-of select="concat($xpath, name())" />   <-------
            <xsl:if test="not(position()=last())">
                <xsl:value-of select="concat('/', $xpath)" />  <-------
            </xsl:if>
        </xsl:for-each>
    </xsl:variable>
    <func:result select="$xpath" />
</func:function>

The variable is not known at that point.

topskip
  • 16,207
  • 15
  • 67
  • 99