[xsl] XSLT 1.0: Grouping Adjacent Elements in Embedded Lists

Subject: [xsl] XSLT 1.0: Grouping Adjacent Elements in Embedded Lists
From: "Joe Heidenreich" <HeidenreichJ@xxxxxxxx>
Date: Thu, 4 Nov 2004 15:21:51 -0500
Hello,

Essentially I'm trying to create a two-tiered embedded list from a flat list
in which I need to group by adjacent like items.

<OL_LI> = Ordered List Items
<EM_OL_LI> = Embedded Ordered List Items

Sample Input is:

	<OL_LI>Top: Item 1</OL_LI>
	<EM_OL_LI>Sub A: Item 1</EM_OL_LI>
	<OL_LI>Top: Item 2</OL_LI>
	<EM_OL_LI>Sub B: Item 1</EM_OL_LI>
	<EM_OL_LI>Sub B: Item 2</EM_OL_LI>
	<EM_OL_LI>Sub B: Item 3</EM_OL_LI>
	<OL_LI>Top: Item 3<OL_LI>
	<EM_OL_LI>Sub C: Item 1</EM_OL_LI>
	<EM_OL_LI>Sub C: Item 2<EM_OL_LI>



Desired Output is:

	<p>
	   <ol>
	      <li>Top: Item 1</li>
	      <p>
	         <ol>
	            <li>Sub A: Item 1</li>
	         </ol>
	      </p>
	      <li>Top: Item 2</li>
	      <p>
	         <ol>
	            <li>Sub B: Item 1</li>
	            <li>Sub B: Item 2</li>
	            <li>Sub B: Item 3</li>
	         </ol>
	      </p>
	      <li>Top: Item 3</li>
	      <p>
	         <ol>
	            <li>Sub C: Item 1</li>
	            <li>Sub C: Item 2</li>
	         </ol>
	      </p>
	   </ol>
	</p>




My Current Transform looks like this:

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

	<xsl:template match="OL_LI" mode="li">
	   <li><xsl:apply-templates /></li>
	   <xsl:apply-templates select="following-sibling::*[1][self::EM_OL_LI]"/>
	   <xsl:apply-templates select="following-sibling::*[1][self::OL_LI]"
mode="li"/>
	</xsl:template>

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

	<xsl:template match="EM_OL_LI" mode="li">
	   <li><xsl:apply-templates/></li>
	   <xsl:apply-templates select="following-sibling::*[1][self::EM_OL_LI]"
mode="li"/>
	</xsl:template>




However, my current output looks like this:

	<p>
	   <ol>
	      <li>Top: Item 1</li>
	      <p>
	         <ol>
	            <li>Sub A: Item 1</li>
	         </ol>
	      </p>
	   </ol>
	</p>

	<p>
	   <ol>
	      <li>Top: Item 2</li>
	      <p>
	         <ol>
	            <li>Sub B: Item 1</li>
	            <li>Sub B: Item 2</li>
	            <li>Sub B: Item 3</li>
	         </ol>
	      </p>
	   </ol>
	</p>

	<p>
	   <ol>
	      <li>Top: Item 3</li>
	      <p>
	         <ol>
	            <li>Sub C: Item 1</li>
	            <li>Sub C: Item 2</li>
	         </ol>
	      </p>
	   </ol>
	</p>

And it is separated into 3 separate lists. The inner list portion is working
fine. What seems to be tripping me up is that the top level <ol> tag is
closing before I want it to.
I'm pretty sure I have to edit this part to account for the case when
preceding-sibling is <EM_OL_LI>

	 <xsl:if test="not(preceding-sibling::*[1][self::OL_LI])">
	      <p>
	         <ol>
	            <xsl:apply-templates select="." mode="li"/>
	         </ol>
	      </p>
	   </xsl:if>

But my attempts have been fruitless. This is a condensed version of what I'm
doing. I also have to account of embedded unordered lists. The current
transformation works great for non-embedded lists as well, which is something
I have to handle. Any help would be greatly appreciated.
And if someone could explain to me the difference between [self::OL_LI] and
[OL_LI] that would be an added educational bonus. Thanks!

-Joe

Current Thread