Hi Emilio,
I have a XML file such as:
<Content>
<Paragraph bullet='false'>
<Text txt='Hello World'/>
</Paragraph>
<Paragraph bullet='true'>
<Text txt='First Bulleted Hello World'/>
</Paragraph>
<Paragraph bullet='true'>
<Text txt='Second Bulleted Hello World'/>
</Paragraph>
<Paragraph bullet='false'>
<Text txt='A normal line of text'/>
</Paragraph>
<Paragraph bullet='true'>
<Text txt='Another bulleted line'/>
</Paragraph>
<Paragraph bullet='true'>
<Text txt='A second bulleted line'/>
</Paragraph>
</Content>
And I want an HTML output like the following:
<html>
<p>Hello World</p>
<ul>
<li>First Bulleted Hello World</li>
<li>Second Bulleted Hello World</li>
</ul>
<p>A normal line of text</p>
<ul>
<li>Another bulleted line</li>
<li>A second bulleted line</li>
</ul>
</html>
This *is* a grouping problem, though you're right that it's not a
"normal" one. In fact, it's very similar to Dave Holden's "flattening"
problem, and I'd approach it the same way, by stepping through the
<Paragraph> elements one by one:
<xsl:template match="Content">
<html>
<!-- only apply templates to first Paragraph -->
<xsl:apply-templates select="Paragraph[1]" />
</html>
</xsl:template>
<xsl:template match="Paragraph[(_at_)bullet = 'false']">
<!-- create p element -->
<p>
<xsl:apply-templates />
</p>
<!-- step on to next Paragraph element -->
<xsl:apply-templates select="following-sibling::Paragraph[1]" />
</xsl:template>
<xsl:template match="Paragraph[(_at_)bullet = 'true']">
<!-- create ul element -->
<ul>
<!-- populate by applying templates in item mode -->
<xsl:apply-templates select="." mode="item" />
</ul>
<!-- step on to next non-bulleted Paragraph -->
<xsl:apply-templates
select="following-sibling::Paragraph[(_at_)bullet = 'false'][1]" />
</xsl:template>
<xsl:template match="Paragraph[(_at_)bullet = 'true']" mode="item">
<!-- create list item -->
<li>
<xsl:apply-templates />
</li>
<!-- step on to next Paragraph -->
<xsl:apply-templates select="following-sibling::Paragraph[1]"
mode="item" />
</xsl:template>
<!-- do nothing -->
<xsl:template match="Paragraph[(_at_)bullet = 'false']" mode="item" />
<xsl:template match="Text">
<xsl:value-of select="@txt" />
</xsl:template>
It's a lot easier in XSLT 2.0:
<xsl:template match="Content">
<html>
<xsl:for-each-group select="Paragraph"
group-adjacent="@bullet">
<xsl:choose>
<xsl:when test="@bullet = 'false'">
<xsl:apply-templates select="current-group()" />
</xsl:when>
<xsl:otherwise>
<ul>
<xsl:apply-templates select="current-group()" />
</ul>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</html>
</xsl:template>
<xsl:template match="Paragraph[(_at_)bullet = 'false']">
<p><xsl:apply-templates /></p>
</xsl:template>
<xsl:template match="Paragraph[(_at_)bullet = 'true']">
<li><xsl:apply-templates /></li>
</xsl:template>
<xsl:template match="Text">
<xsl:value-of select="@txt" />
</xsl:template>
Cheers,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list