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 <>)
|