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

Re: Count previous-siblings w/same attribute value up

Subject: Re: Count previous-siblings w/same attribute value up to attribute value - 1 possible?
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Mon, 12 Dec 2011 21:01:21 -0500
Re:  Count previous-siblings w/same attribute value up
At 2011-12-12 16:54 -0800, Lou Argyres wrote:
I hope this makes sense.

I have "flat" outline list structures, the numbering of which is
controlled by a "level" attribute, that I renumber based on name-spaced
change tracking tags where I need to output Accept-All and Reject-All
versions to be redlined in other application formats after
transformations. (They're good for unsophisticated users who have
trouble editing embedded lists.)

The best I've come up with is a recursive template to count previous
same level items and stop at a lower level (skipping adds/deletes as
needed).

Is there an XPATH-2 select that can count preceding-siblings up to the
first preceding @level = $lvl-1?

 <xsl:variable name="lvl" select="@level"/>
 ...
 ... select="(count(preceding-sibling::section[@level=$lvl]) + 1) -
count(preceding-sibling::section[@level=$lvl][not(following-sibling::sec
tion[preceding-sibling::section[@level=number($lvl)-1][1]])])"

picks up all previous same-level items.

<flatOutline>
 <item numDisplay="I." level="1" />
 <item numDisplay="II." level="1" />
  <item numDisplay="A." level="2" />
  <item numDisplay="B." level="2" />
  <item numDisplay="C." level="2" />
 <item numDisplay="III." level="1"/>
  <item numDisplay="A." level="2"/>
   <item numDisplay="1." level="3" />
   <item numDisplay="2." level="3" />
   <item numDisplay="3." level="3" />
   <item numDisplay="4." level="3" />
  <item numDisplay="B." level="2"/>
   <item numDisplay="1." level="3" />
   <item numDisplay="2." level="3" />
   <item numDisplay="3." level="3" />
  <item numDisplay="C." level="2"/>
</flatOutline>

Lou Argyres
Continuing Education of the Bar - California
Oakland, CA
Lou.Argyres@xxxxxxxxxxxx

If you are simply counting, then the following works in both XSLT 1 and XSLT 2, as it takes the difference between the count to the beginning and the count to the beginning from the last disqualifying entry (note the two-step location path in the second count() function call):


t:\ftemp>xslt lou.xml lou1.xsl
<?xml version="1.0" encoding="utf-8"?>
<item numDisplay="I." level="1">1</item>
<item numDisplay="II." level="1">2</item>
<item numDisplay="A." level="2">1</item>
<item numDisplay="B." level="2">2</item>
<item numDisplay="C." level="2">3</item>
<item numDisplay="III." level="1">3</item>
<item numDisplay="A." level="2">1</item>
<item numDisplay="1." level="3">1</item>
<item numDisplay="2." level="3">2</item>
<item numDisplay="3." level="3">3</item>
<item numDisplay="4." level="3">4</item>
<item numDisplay="B." level="2">2</item>
<item numDisplay="1." level="3">1</item>
<item numDisplay="2." level="3">2</item>
<item numDisplay="3." level="3">3</item>
<item numDisplay="C." level="2">3</item>
t:\ftemp>type lou1.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">
<xsl:output indent="yes"/>

<xsl:template match="/">
  <xsl:for-each select="/*/item">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:value-of
        select="count(preceding-sibling::item[@level=current()/@level]) -
                count(preceding-sibling::item[@level&lt;current()/@level][1]/
                      preceding-sibling::item[@level=current()/@level]) + 1"/>
    </xsl:copy>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>
t:\ftemp>


If you actually want to do something with the groups at each level, then it is best to use XSLT 2:


t:\ftemp>xslt2 lou.xml lou2.xsl
<?xml version="1.0" encoding="UTF-8"?>
<section level="1">
   <item numDisplay="I." level="1"/>
</section>
<section level="1">
   <item numDisplay="II." level="1"/>
   <section level="2">
      <item numDisplay="A." level="2"/>
      <item numDisplay="B." level="2"/>
      <item numDisplay="C." level="2"/>
   </section>
</section>
<section level="1">
   <item numDisplay="III." level="1"/>
   <section level="2">
      <item numDisplay="A." level="2"/>
      <section level="3">
         <item numDisplay="1." level="3"/>
         <item numDisplay="2." level="3"/>
         <item numDisplay="3." level="3"/>
         <item numDisplay="4." level="3"/>
      </section>
   </section>
   <section level="2">
      <item numDisplay="B." level="2"/>
      <section level="3">
         <item numDisplay="1." level="3"/>
         <item numDisplay="2." level="3"/>
         <item numDisplay="3." level="3"/>
      </section>
   </section>
   <section level="2">
      <item numDisplay="C." level="2"/>
   </section>
</section>
t:\ftemp>type lou2.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">
<xsl:output indent="yes"/>

<xsl:template match="/" name="do-next-group">
  <xsl:param name="group" select="/*/item"/>
  <xsl:param name="level" select="1"/>
  <xsl:choose>
    <xsl:when test="$group[@level!=$level]">
      <!--then more splitting of the group is necessary-->
      <xsl:for-each-group select="$group"
                          group-starting-with="item[@level=$level]">
        <section level="{$level}">
          <!--put the current level into this section-->
          <xsl:copy-of select="current-group()[@level=$level]"/>
          <!--only nest when this group has members from deeper levels-->
          <xsl:if test="current-group()[@level!=$level]">
            <xsl:call-template name="do-next-group">
              <xsl:with-param name="group"
                              select="current-group()[@level!=$level]"/>
              <xsl:with-param name="level" select="$level+1"/>
            </xsl:call-template>
          </xsl:if>
        </section>
      </xsl:for-each-group>
    </xsl:when>
    <xsl:otherwise>
      <!--no more splitting of the group is necessary-->
      <section level="{$level}">
        <xsl:copy-of select="$group"/>
      </section>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

</xsl:stylesheet>
t:\ftemp>


I hope this helps.


. . . . . . . . . . Ken

--
Contact us for world-wide XML consulting and instructor-led training
Free 5-hour video lecture: XSLT/XPath 1.0 & 2.0 http://ude.my/t37DVX
Crane Softwrights Ltd.            http://www.CraneSoftwrights.com/s/
G. Ken Holman                   mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
Google+ profile: https://plus.google.com/116832879756988317389/about
Legal business disclaimers:    http://www.CraneSoftwrights.com/legal

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-2013 All Rights Reserved.