photo_tom
photo_tom

Reputation: 7342

<xsl:when test="//..."> syntax

I'm trying to debug an existing XSLT file and have the following elements

    <xsl:choose>
        <xsl:when test="//j:Node_A/j:Node_B/j:Node_c">
            <xsl:apply-templates select="//j:Node_A/j:Node_B/j:Node_c />
        </xsl:when>
        <xsl:otherwise>
            <xsl:call-template name="NoMatch" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

As I understand the test statement it is looking for a structure like the following in the XML and when the structure is found applies the template.

  <node_a>
    <node_b>
      <node_c>
          DATA
      </node_c>
    </node_b>
  </node_a>

What I don't understand is the meaning of the //.

Upvotes: 1

Views: 594

Answers (3)

Ian Roberts
Ian Roberts

Reputation: 122414

The precise definition of // in XPath is that it is shorthand for

/descendant-or-self::node()/

including the leading and trailing slashes. The path a//b is effectively the union of a/b, a/*/b, a/*/*/b, etc. for any number of repetitions of /*

In practice this means you can use it when you want to look for descendant nodes at any level rather than just immediate children, e.g. /node_a//node_c.

Upvotes: 2

helderdarocha
helderdarocha

Reputation: 23627

// represents the descendant:: or descendant-or-self:: axis in XPath. It should be followed by a node test which can be:

  • qualified name of an element. Ex: //j:node_a (matches all descendant node_a elements in the namespace represented by the prexif j - same as //descendant-or-self::j:node_a)
  • an * which represents any element. Ex: //* (matches all descendant elements - same as //descendant-or-self::*)
  • text(), processing-instruction() or comment(). Ex: //text() (matches all descendant text nodes - same as //descendant-or-self::text())
  • another axis. Ex: //@* (matches all attributes - same as //attribute::*)

You can use it anywhere inside the XPath expression to skip levels in a tree. For example:

//j:Node_A//j:Node_c

will match all Node_c elements which have a Node_A ancestor.

Note that XPath expressions are case sensitive: Node_a != Node_A != node_a.

Your XSLT selects elements which are prefixed. It should also have a declaration somewhere (normally in the <xsl:stylesheet> element) which associates that prefix with a namespace for your expressions to work.

Upvotes: 1

DwB
DwB

Reputation: 38328

This is actually an XPath question.

The "//" indicates "not starting at root"

/blam/hoot/kapow only matches if the root node is blam.

//blam/hoot/kapow matches if there is a node pattern of blam containing a hoot containing a kapow.

The second test will match the blam/hoot/kapow in this:

<schmar>
   <blam>
     <hoot>
       <kapow>
       </kapow>
     </hoot>
   </blam>
</schmar>

The first test will not match in the xml above.

Upvotes: 1

Related Questions