views:

202

answers:

2

I'm using the following to match all <section>s with a revision attribute set. <section>can appear at many different levels of the document tree, always contained within <chapter>s.

<xsl:for-each select="//section[@revision]">
    <!-- Do one thing if this is the first section 
           matched in this chapter -->

    <!-- Do something else if this section is in the same 
           chapter as the last section matched -->
</xsl:for-each>

As the comments say, I need to make each for-each iteration aware of the chapter to which the previous matched section belonged. I know that <xsl:variable>s are actually static once set, and that <xsl:param> only applies to calling templates.

This being Docbook, I can retreive a section's chapter number with:

<xsl:apply-templates select="ancestor::chapter[1]" mode="label.markup" />

but I think it can be done with purely XPath.

Any ideas? Thanks!

A: 

position() will return your position within the current for-each iteration. The first iteration, IIRC, will return 0, so testing for "position()=0" will tell you if you are in the first iteration.

Phil Nash
The iteration count doesn't matter; I need to pass the chapter number from one iteration to the next.
carillonator
+1  A: 

Not sure if I unterstood your requirements 100%, but…

<xsl:variable name="sections" select="//section[@revision]" />

<xsl:for-each select="$sections">
  <xsl:variable name="ThisPos" select="position()" />
  <xsl:variable name="PrevMatchedSection" select="$sections[$ThisPos - 1]" />
  <xsl:choose>
    <xsl:when test="
      not($PrevMatchedSection)
      or
      generate-id($PrevMatchedSection/ancestor::chapter[1])
      !=
      generate-id(ancestor::chapter[1])
    ">
      <!-- Do one thing if this is the first section 
           matched in this chapter -->
    </xsl:when>
    <xsl:otherwise>
      <!-- Do something else if this section is in the same 
           chapter as the last section matched -->
    </xsl:otherwise>
  </xsl:choose>  
</xsl:for-each>

However, I suspect this whole thing can be solved more elegantly with a <xsl:template> / <xsl:apply-templates> approach. But without seeing your input and expected output this is hard to say.

Tomalak
thanks, I'm working on this. One thing, though: your `sections` variable defined before the `for-each` is not available inside the `for-each` loop itself. Easily fixed by just not using the constant, though.
carillonator
Of course is the variable available inside the `<xsl:for-each>`. The only thing that was not right was the `[position() - 1]` predicate, which I have fixed now.
Tomalak