[Home] [By Thread] [By Date] [Recent Entries]

Subject: Re: for-each-group throughout a document
From: "David Carlisle d.p.carlisle@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 25 Sep 2026 15:56:39 -0000
If I add

    <xsl:template match="li[preceding-sibling::*[1]/self::li]"/>
    <xsl:template match="li[not(preceding-sibling::*[1]/self::li)]">
     <list>
      <xsl:apply-templates select="." mode="li"/>
     </list>
    </xsl:template>

    <xsl:template match="li" mode="li">
     <xsl:copy-of select="."/><!-- or whatever-->
     <xsl:apply-templates mode="li"
select="following-sibling::*[1][self::li]"/>
    </xsl:template>


to the end of your stylesheet I get

                  <concept id="d1e29">
                     <title>Heading 4</title>
                     <conbody>
                        <para>Some text under heading 4</para>
                        <list>
                           <li>list item under heading 4</li>
                           <li>list item under heading 4</li>
                           <li>list item under heading 4</li>
                        </list>
                     </conbody>
                  </concept>


and similar for the first list



On Fri, 25 Sept 2026 at 16:38, rick@xxxxxxxxxxxxxx <
xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:

> Hi All,
>
>
>
> I have a flat XML structure like this that I need to add hierarchy to.
>
>
>
> <?xml version="1.0" encoding="UTF-8"?>
> <doc>
>     <h1>Heading 1</h1>
>     <para>Some text under heading 1</para>
>     <para>Some text under heading 1</para>
>     <li>list item under heading 1</li>
>     <li>list item under heading 1</li>
>     <li>list item under heading 1</li>
>     <li>list item under heading 1</li>
>     <para>Some text under heading 1</para>
>     <h2>Heading 2</h2>
>     <h3>Heading 3</h3>
>     <para>Some text under heading 3</para>
>     <para>Some text under heading 3</para>
>     <h4>Heading 4</h4>
>     <para>Some text under heading 4</para>
>     <li>list item under heading 4</li>
>     <li>list item under heading 4</li>
>     <li>list item under heading 4</li>
> </doc>
>
> My current stylesheet gives me this, which is what I want:
>
>
>
> <?xml version="1.0" encoding="UTF-8"?>
> <concept id="d1e3">
>    <title>Heading 1</title>
>    <conbody>
>       <para>Some text under heading 1</para>
>       <para>Some text under heading 1</para>
>       <li>list item under heading 1</li>
>       <li>list item under heading 1</li>
>       <li>list item under heading 1</li>
>       <li>list item under heading 1</li>
>       <para>Some text under heading 1</para>
>       <concept id="d1e28">
>          <title>Heading 2</title>
>          <conbody>
>             <concept id="d1e31">
>                <title>Heading 3</title>
>                <conbody>
>                   <para>Some text under heading 3</para>
>                   <para>Some text under heading 3</para>
>                   <concept id="d1e41">
>                      <title>Heading 4</title>
>                      <conbody>
>                         <para>Some text under heading 4</para>
>                         <li>list item under heading 4</li>
>                         <li>list item under heading 4</li>
>                         <li>list item under heading 4</li>
>                      </conbody>
>                   </concept>
>                </conbody>
>             </concept>
>          </conbody>
>       </concept>
>    </conbody>
> </concept>
>
> However, I have <li> elements that need to be grouped as well; they can
> appear just about anywhere in the source XML. Is there a generalized
> solution where I can address grouping anywhere in my structure? Here is my
> current stylesheet.
>
>
>
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>     xmlns:xs="http://www.w3.org/2001/XMLSchema"
>     xmlns:math="http://www.w3.org/2005/xpath-functions/math"
>     exclude-result-prefixes="xs math"
>     version="3.0" expand-text="yes">
>
>     <xsl:output indent="yes"/>
>
>     <xsl:template match="/">
>         <xsl:apply-templates/>
>     </xsl:template>
>
>     <xsl:template match="*doc*">
>         <xsl:for-each-group select="*" group-starting-with="*h1*">
>             <xsl:apply-templates select="." mode="group"/>
>         </xsl:for-each-group>
>     </xsl:template>
>
>     <xsl:template match="*h1*" mode="group">
>         <concept id="{*generate-id*()}">
>             <title><xsl:apply-templates/></title>
>             <xsl:choose>
>                 <xsl:when test="*not*(following-sibling::*[1][self::
> *title*])">
>                     <conbody>
>                         <xsl:for-each-group select="*current-group*()
> *except* ." group-starting-with="*h2*">
>                             <xsl:apply-templates select="." mode="group"/>
>                         </xsl:for-each-group>
>                     </conbody>
>                 </xsl:when>
>                 <xsl:otherwise>
>                     <xsl:for-each-group select="*current-group*() *except*
> ." group-starting-with="*h2*">
>                         <xsl:apply-templates select="." mode="group"/>
>                     </xsl:for-each-group>
>                 </xsl:otherwise>
>             </xsl:choose>
>         </concept>
>     </xsl:template>
>
>     <xsl:template match="*h2*" mode="group">
>         <concept id="{*generate-id*()}">
>             <title><xsl:apply-templates/></title>
>             <xsl:choose>
>                 <xsl:when test="*not*(following-sibling::*[1][self::
> *heading3*])">
>                     <conbody>
>                         <xsl:for-each-group select="*current-group*()
> *except* ." group-starting-with="*h3*">
>                             <xsl:apply-templates select="." mode="group"/>
>                         </xsl:for-each-group>
>                     </conbody>
>                 </xsl:when>
>                 <xsl:otherwise>
>                     <xsl:for-each-group select="*current-group*() *except*
> ." group-starting-with="*h3*">
>                         <xsl:apply-templates select="." mode="group"/>
>                     </xsl:for-each-group>
>                 </xsl:otherwise>
>             </xsl:choose>
>         </concept>
>     </xsl:template>
>
>     <xsl:template match="*h3*" mode="group">
>         <concept id="{*generate-id*()}">
>             <title><xsl:apply-templates/></title>
>             <xsl:choose>
>                 <xsl:when test="*not*(following-sibling::*[1][self::*h4*
> ])">
>                     <conbody>
>                         <xsl:for-each-group select="*current-group*()
> *except* ." group-starting-with="*h4*">
>                             <xsl:apply-templates select="." mode="group"/>
>                         </xsl:for-each-group>
>                     </conbody>
>                 </xsl:when>
>                 <xsl:otherwise>
>                     <xsl:for-each-group select="*current-group*() *except*
> ." group-starting-with="*h4*">
>                         <xsl:apply-templates select="." mode="group"/>
>                     </xsl:for-each-group>
>                 </xsl:otherwise>
>             </xsl:choose>
>         </concept>
>     </xsl:template>
>
>     <xsl:template match="*h4*" mode="group">
>         <concept id="{*generate-id*()}">
>             <title><xsl:apply-templates/></title>
>             <conbody>
>                 <xsl:apply-templates select="*current-group*() *except*
> ."/>
>             </conbody>
>         </concept>
>     </xsl:template>
>
>     <xsl:template match="*" mode="group">
>         <xsl:apply-templates select="*current-group*()"/>
>     </xsl:template>
>
>     <xsl:mode on-no-match="shallow-copy"/>
>
> </xsl:stylesheet>
>
>
>
> Thank you for your help.
>
>
>
> Rick Quatro
>
>
> XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
> EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/2739265> (by
> email <>)

Current Thread
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member