"Herman Kwok" <herman(_dot_)kwok(_at_)technologist(_dot_)com> wrote in message
news:20031118102107(_dot_)7888(_dot_)qmail(_at_)iname(_dot_)com(_dot_)(_dot_)(_dot_)
Sorry for my late reply as I was out of town.
Thanks Dimitre for the "exslt:node-set()" solution and Jarkko for the
"xalan:nodeset()" solution.
Does it mean that there is no solution without using processor dependent
solution nor external library in XSLT 1.0?
No.
Well, I am new to XSLT. I suspect that there are some limitations in node
set in XSLT. That was why the function was extended via
using external library or via enhancing a processor. Am I correct?
No. Actually it has been proven that XSLT is Turing-complete. This means
that any algorithm, that can be implemented on a Turing machine (or on a
programming system that is as powerful or less than a Turing machine) can be
implemented in XSLT.
However, not using the xxx:node-set() extension function would be a little
more difficult and probably a little bit less efficient.
Here is a solution that does not use any extension functions. This
transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pNumInGroup" select="3"/>
<xsl:key name="kfromID" match="item" use="generate-id()"/>
<xsl:template match="/">
<xsl:variable name="vIDs">
<xsl:for-each select="/*/item">
<xsl:sort select="@desc"/>
<xsl:value-of select="concat(generate-id(), '|')"/>
</xsl:for-each>
</xsl:variable>
<xsl:call-template name="group">
<xsl:with-param name="pIDs" select="$vIDs"/>
<xsl:with-param name="pNumInGroup" select="$pNumInGroup"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="group">
<xsl:param name="pIDs" />
<xsl:param name="pNumInGroup" select="1"/>
<xsl:if test="contains($pIDs, '|')">
<group>
<xsl:call-template name="fillElements">
<xsl:with-param name="pIDs" select="$pIDs"/>
<xsl:with-param name="pNumInGroup" select="$pNumInGroup"/>
</xsl:call-template>
</group>
<xsl:variable name="vOffset">
<xsl:call-template name="getOffset">
<xsl:with-param name="pIDs" select="$pIDs"/>
<xsl:with-param name="pNumInGroup" select="$pNumInGroup"/>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="group">
<xsl:with-param name="pIDs" select="substring($pIDs, $vOffset +
1)"/>
<xsl:with-param name="pNumInGroup" select="$pNumInGroup"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="fillElements">
<xsl:param name="pIDs"/>
<xsl:param name="pNumInGroup" select="1"/>
<xsl:if test="$pNumInGroup > 0 and contains($pIDs, '|')">
<xsl:copy-of select="key('kfromID', substring-before($pIDs, '|'))"/>
<xsl:call-template name="fillElements">
<xsl:with-param name="pIDs" select="substring-after($pIDs, '|')"/>
<xsl:with-param name="pNumInGroup" select="$pNumInGroup - 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="getOffset">
<xsl:param name="pIDs"/>
<xsl:param name="pNumInGroup" select="1"/>
<xsl:param name="pResult" select="0"/>
<xsl:choose>
<xsl:when test="$pNumInGroup > 0 and contains($pIDs, '|')">
<xsl:variable name="vT1" select="substring-before($pIDs, '|')"/>
<xsl:call-template name="getOffset">
<xsl:with-param name="pIDs" select="substring-after($pIDs, '|')"/>
<xsl:with-param name="pNumInGroup" select="$pNumInGroup - 1"/>
<xsl:with-param name="pResult"
select="$pResult
+ string-length(substring-before($pIDs, '|')) + 1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$pResult"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
when applied on your source.xml:
<result>
<item desc="d"/>
<item desc="j"/>
<item desc="k"/>
<item desc="e"/>
<item desc="c"/>
<item desc="g"/>
<item desc="h"/>
<item desc="i"/>
<item desc="f"/>
<item desc="a"/>
<item desc="b"/>
</result>
produces the wanted result:
<group>
<item desc="a"/>
<item desc="b"/>
<item desc="c"/>
</group>
<group>
<item desc="d"/>
<item desc="e"/>
<item desc="f"/>
</group>
<group>
<item desc="g"/>
<item desc="h"/>
<item desc="i"/>
</group>
<group>
<item desc="j"/>
<item desc="k"/>
</group>
=====
Cheers,
Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list