[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

xsl:for-each-group: start groups depending on number o

Subject: xsl:for-each-group: start groups depending on number of group members?
From: Yves Forkl <Y.Forkl@xxxxxx>
Date: Fri, 27 Apr 2007 19:18:26 +0200
 xsl:for-each-group: start groups depending on number o
Relying heavily on xsl:for-each-group in the context of rather complicated transformations, I have run into this situation (and am stuck there...): When specifying, in group-starting-with, the pattern that may start some specific group, I would like to take into account the number of items available for grouping.

More precisely, my group starting pattern must include a filter using preceding-sibling which I do not want to "look beyond" the current sequence of items to be grouped.

Showcasing this in a minimal example (more details below):

INPUT:

<root>
  <A/>
  <sub>a1</sub>
  <B/>
  <sub>b1</sub>
  <sub>b2</sub>
  <sub>b3</sub>
  <C/>
  <sub>c1</sub>
  <sub>c2</sub>
</root>

OUTPUT:

<B_new>
   <sub_new>b1</sub_new>
   <sub_new>b2</sub_new>
   <sub_new>b3</sub_new>
</B_new>

STYLESHEET:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="2.0">

<xsl:output indent="yes"/>

  <xsl:template match="/">
    <xsl:for-each-group
      select="root/*"
      group-starting-with="A|B|C">
      <xsl:apply-templates
        select="current-group()[1]"
        mode="groups_at_root_level"/>
    </xsl:for-each-group>
  </xsl:template>

  <!-- don't care for them now -->
  <xsl:template match="A|C" mode="groups_at_root_level"/>

  <xsl:template match="B" mode="groups_at_root_level">
    <B_new>
      <xsl:variable name="items_total" select="count(current-group())"/>
      <xsl:for-each-group
        select="current-group()"
        group-starting-with="
          B|
          sub[not(
            preceding-sibling::*[position() lt $items_total][A])]">
        <xsl:apply-templates select="current-group()"/>
      </xsl:for-each-group>
    </B_new>
  </xsl:template>

  <xsl:template match="sub">
    <sub_new>
      <xsl:apply-templates/>
    </sub_new>
  </xsl:template>

<xsl:template match="*"/>

</xsl:stylesheet>


I would like to ask your opinion on the preceding-sibling line. If it just read preceding-sibling::A, the output would of course miss all "sub" instances. (Unfortunately, for reasons difficult to explain here, I can't just drop the negated preceding-sibling filter because I need it in some of my group starting patterns.)


Obviously, my above try at restricting the number of preceding siblings to consider to those which are among the items to group is rather limited: When xsl:for-each-group examines the very first item, the first preceding sibling of that will already be outside of the groupable items (while the last item will have many more "acceptable" preceding siblings than the first). This makes me dream of a kind of dynamic position counter returning the position of the current item that xsl:for-each-group is trying to put into a group. Is there such a thing?

Alternatively, how could I restrict sibling tests to the items which are being grouped, inside the pattern of group-starting-with?

Yves

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2007 All Rights Reserved.