21

I have nested xsl:for loops:

<xsl:for-each select="/Root/A">
    <xsl:for-each select="/Root/B">
        <!-- Code -->
    </xsl:for>
</xsl:for>

From within the inner loop, how can I access attributes from the current node in the outer loop?

I keep finding myself writing code like this:

<xsl:for-each select="/Root/A">
    <xsl:variable name="someattribute" select="@SomeAttribute"/>
    <xsl:for-each select="/Root/B">
        <!-- Now can use $someattribute to access data from 'A' -->
    </xsl:for>
</xsl:for>

This doesn't scale very well, as sometimes I need to access several pieces of information and end up creating one variable for each piece. Is there an easier way?

3 Answers 3

26

You can store the entire /Root/A structure in a variable, and make reference to that variable rather than creating a new variable for every attribute and subelement you need to access.

<xsl:for-each select="/Root/A/">
    <xsl:variable name="ROOT_A" select="."/>
    <xsl:for-each select="/Root/B/">
         <!-- Variable is accessed like this: $ROOT_A/@someAttribute
              Just like a normal XML node -->
    </xsl:for-each>
</xsl:for-each>
Sign up to request clarification or add additional context in comments.

2 Comments

+1, but it might be worth editing the variable name to make its function more clear.
That's what I usually end up doing ;-p
8

Welbog has answered it well - but just to note you appear to be doing a cartesion (cross) join - is that intentional? If you are trying to do a regular join (with a predicate etc), then you want want to look into <xsl:key/> - i.e. declare a key:

<xsl:key name="BIndex" match="/Root/B" use="SomeChildNode"/>

then consume in your predicate:

<xsl:for-each select="/Root/A/">
    <xsl:variable name="ROOT_A" select="."/>
    <xsl:for-each select="key('BIndex', LocalNode)">
     <!-- -->
    </xsl:for-each>
</xsl:for-each>

This should be equivalent to (but much faster than) the predicate:

    <xsl:for-each select="/Root/B[SomeChildNode = current()/LocalNode]">

If you are grouping the data, then look at Muenchian grouping

3 Comments

Thanks for the tips.. I'm relatively new to XSLT and aren't completely sure what I'm doing yet. Once I get things working I'll take a look at what you suggest to see if there's an easier way.
Note: It took me some effort to decipher the 'cartesian-join vs. predicate-join part' above. So just noting down the difference for people new to it. Basically if you have a 'm' number of nodes in A and 'n' number of nodes in B, cartesian join will result in m*n nodes whereas predicate-join joins on a particular key i.e. join A AND B where A.key = B.key.
To check against the element name of current (the element the for-loop iterates over), you can use name(current()) - don't try current()/name(), it's not allowed.
0

The following could also be used :

    <xsl:for-each select="ns:attribute">
        <name><xsl:value-of select="ns:name" /></name>              
        <xsl:for-each select="ns:value">
        <value><xsl:value-of select="."/></value>       
        </xsl:for-each>
    </xsl:for-each>      

For parsing the XML document ..

 <ns:attribute>
      <ns:name>name</ns:name>
      <!--1 or more repetitions:-->
      <ns:value>Rahul</ns:value>
      <ns:value>Sushovan</ns:value>
</ns:attribute>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.