Good afternoon! I have a big trouble with xsl..
On enter I have this XML of menu with multiple <chapter />
s, that consits multiple <paragraph />
s, that consists multiple <text />
s or <quote />
s:
<menu>
<chapter>
<name>Chapter 1</name>
<paragraph>
<name>Paragraph 1</name>
<text>
<name>Text 1</name>
</text>
<text>
<name>Text 2</name>
</text>
<text>
<name>Text 3</name>
</text>
</paragraph>
<paragraph>
<name>Paragraph 2</name>
<quote>
<name>Quote 1</name>
</quote>
<quote>
<name>Quote 2</name>
</quote>
</paragraph>
<paragraph>
<name>Paragraph 3</name>
<quote>
<name>Quote 3</name>
</quote>
</paragraph>
<paragraph>
<name>Paragraph 4</name>
<text>
<name>Text 4</name>
</text>
</paragraph>
</chapter>
</menu>
On exit I want have something like this (paragraphs that proportionally separated by rows - the same quantity of paragraphs + texts + quotes in each row):
<h1>Chapter 1</h1>
<div class="clearfix">
<div class="row">
<h2>Paragraph 1</h2>
<p class="text">Text 1</p>
<p class="text">Text 2</p>
<p class="text">Text 3</p>
</div>
<div class="row">
<h2>Paragraph 2</h2>
<p class="quote">Quote 1</p>
<p class="quote">Quote 2</p>
</div>
<div class="row">
<h2>Paragraph 3</h2>
<p class="quote">Quote 3</p>
<h2>Paragraph 4</h2>
<p class="text">Text 4</p>
</div>
</div>
I'm trying to give this result by xsl:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output xmlns="http://www.w3.org/TR/xhtml1/strict" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" encoding="utf-8" indent="yes" method="html" omit-xml-declaration="no" version="1.0" media-type="text/xml"/>
<xsl:variable name="n" select="number(3)" />
<xsl:template match="/">
<xsl:apply-templates select="menu" />
</xsl:template>
<xsl:template match="/menu">
<xsl:apply-templates select="chapter" />
</xsl:template>
<xsl:template match="chapter">
<h1><xsl:value-of disable-output-escaping="yes" select="name" /></h1>
<xsl:if test="paragraph/node()">
<div class="clearfix">
<div class="row">
<xsl:apply-templates select="paragraph" />
</div>
</div>
</xsl:if>
</xsl:template>
<xsl:template match="chapter/paragraph">
<xsl:variable name="limit" select="ceiling((count(../paragraph) + count(../paragraph/*[name() = 'text' or name() = 'quote'])) div $n)" />
<xsl:variable name="position" select="position() - 1" />
<xsl:variable name="prev_count" select="count(preceding-sibling::paragraph/*[name() = 'text' or name() = 'quote'])" />
<h2><xsl:value-of disable-output-escaping="yes" select="name" /></h2>
<xsl:if test="text/node() or quote/node()">
<xsl:for-each select="text">
<p class="text"><xsl:value-of disable-output-escaping="yes" select="name" /></p>
</xsl:for-each>
<xsl:for-each select="quote">
<p class="quote"><xsl:value-of disable-output-escaping="yes" select="name" /></p>
</xsl:for-each>
</xsl:if>
<xsl:variable name="prev_index" select="round(($position + $prev_count) div $limit)" />
<xsl:variable name="next_index" select="round(($position + 1 + $prev_count + count(*[name() = 'text' or name() = 'quote'])) div $limit)" />
<xsl:if test="$prev_index != $next_index">
<xsl:text disable-output-escaping="yes"></div><div class="row"></xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
But this code return good results don't always. Maybe somebody have a better solution? I'm sorry for this worst code ;(
UPD: I can't split paragraphs - just group by rows