Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSLT - find position() when inside a nested for-each

I'm using XSLT to perform a transformation on some fairly complex XML. In order to achieve the output I need to, I've had to create a nested for loop something like the following:

Source XML

<root>
  <element1>
    <child>
      <aaa></aaa>
      <bbb></bbb>
    </child>
  </element1>
  <element2/>
  <element3/>
  <element3/>
  <element3/>
</root>

XSLT

<xsl:for-each select="element3">
  <!-- Do some stuff -->

  <xsl:for-each select="../element1/child/*">
    <!-- Do some more stuff -->
  </xsl:for-each>
</xsl:for-each>

Problem

What I'm trying to do here is whilst in my nested loop (on ../element1/child/*) - I'd like to find out:

  1. The position of the element I'm currently looping - if, for example, I was currently focused on <bbb> then this position (I think) would be '1'
  2. The position of the parent loop (on element3) - so if, for example, I was on the third instance of <element3> and then looping through ../element1/child/* and was focused on <aaa> - the two values I would be after would be '2' and '0'.

Ideally, I'd like to be able to assign these values to a variable. I've tried using the position() notation like below but this doesn't seem to be working.

<xsl:for-each select="../element1/child/*">
  <xsl:variable name="postion_current_loop" select="position()"/>
  <xsl:variable name="postion_parent_loop" select="??????"/>
  <!-- Do some more stuff -->
</xsl:for-each>

If anyone has any ideas on how I could achieve this that would be greatly appreciated! I'm using XSLT 2.0, but am open to solutions using XSLT 1.0 if need be. Thanks in advance.

like image 493
danw Avatar asked Mar 19 '23 01:03

danw


1 Answers

You should try modifying your input to:

<root>
  <element1>
    <child>
      <aaa>1a</aaa>
      <bbb>2a</bbb>
    </child>
  </element1>
  <element2/>
  <element3>3a</element3>
  <element3>3b</element3>
  <element3>3c</element3>
</root>

then see what you get with:

<xsl:template match="/">
    <test>
        <xsl:for-each select="root/element3">
        <xsl:variable name="parent-position" select="position()" />
        <xsl:variable name="parent-value" select="." />
            <xsl:for-each select="../element1/child/*">
                <item value="{.}" parent-value="{$parent-value}" parent-position="{$parent-position}" position="{position()}"/>
            </xsl:for-each>
        </xsl:for-each>    
    </test>
</xsl:template>
like image 156
michael.hor257k Avatar answered Apr 01 '23 10:04

michael.hor257k