"Michael Kay" <mhk(_at_)mhk(_dot_)me(_dot_)uk> wrote in message
news:000b01c3c0a4$b7bd9390$6401a8c0(_at_)pcukmka(_dot_)(_dot_)(_dot_)
Dimitre, I would be very grateful if you can make the source files and
stylesheets for this test available.
Many thanks,
Michael Kay
Yes Mike,
Here they are:
source1000.xml:
===========
<records>
<record n="1" type="normal"/>
<record n="2" type="normal"/>
<record n="3" type="continuation"/>
<record n="4" type="continuation"/>
<record n="5" type="continuation"/>
<record n="6" type="continuation"/>
<record n="7" type="continuation"/>
<!--..............................................................
This means "and so on"
.....................................................................
-->
<record n="1000" type="continuation"/>
<record n="1001" type="continuation"/>
<record n="1002" type="continuation"/>
<record n="1003" type="normal"/>
<record n="1004" type="normal"/>
</records>
source2000.xml:
===========
<records>
<record n="1" type="normal"/>
<record n="2" type="normal"/>
<record n="3" type="continuation"/>
<record n="4" type="continuation"/>
<record n="5" type="continuation"/>
<record n="6" type="continuation"/>
<record n="7" type="continuation"/>
<!--..............................................................
This means "and so on"
.....................................................................
-->
<record n="2000" type="continuation"/>
<record n="2001" type="continuation"/>
<record n="2002" type="continuation"/>
<record n="2003" type="normal"/>
<record n="2004" type="normal"/>
</records>
These can be easily generated with the following XSLT 2.0 stylesheet,
setting the $pnumNodes respectively to 1000 and 2000.
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pnumNodes" select="1000"/>
<xsl:template match="/">
<records>
<record n="1" type="normal"/>
<record n="2" type="normal"/>
<xsl:for-each select="3 to $pnumNodes + 2">
<record n="{.}" type="continuation"/>
</xsl:for-each>
<record n="{$pnumNodes + 3}" type="normal"/>
<record n="{$pnumNodes + 4}" type="normal"/>
</records>
</xsl:template>
</xsl:stylesheet>
Now the different transformations.
I. Recursive transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="records">
<records>
<xsl:apply-templates select="record[(_at_)type = 'normal']"/>
</records>
</xsl:template>
<xsl:template match="record[(_at_)type = 'normal']">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
<xsl:apply-templates
select="following-sibling::record[1][(_at_)type='continuation']"/>
</xsl:copy>
</xsl:template>
<xsl:template match="record[(_at_)type = 'continuation']">
<xsl:copy-of select="." />
<xsl:apply-templates
select="following-sibling::record[1][(_at_)type='continuation']"/>
</xsl:template>
</xsl:stylesheet>
II. Key-based transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="kCont" match="record[(_at_)type='continuation']"
use="generate-id(preceding-sibling::record
[(_at_)type = 'normal'][1]
)"/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="records">
<records>
<xsl:apply-templates select="record[(_at_)type = 'normal']" />
</records>
</xsl:template>
<xsl:template match="record[(_at_)type = 'normal']">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
<xsl:apply-templates
select="key('kCont', generate-id())"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
III. Non-recursive transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vposArray">
<xsl:value-of select="'|'"/>
<xsl:for-each select="/*/record">
<xsl:if test="@type = 'normal'">
<xsl:value-of select="concat(position(), '|')"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:template match="@* | node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="records">
<records>
<xsl:apply-templates select="record"/>
</records>
</xsl:template>
<xsl:template match="record">
<xsl:choose>
<xsl:when test="not(@type='normal')">
<xsl:call-template name="identity"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="vPos" select="position()"/>
<xsl:variable name="vposNext"
select="substring-before(
substring-after($vposArray,
concat('|',
position(),
'|'
)
),
'|'
)"/>
<xsl:variable name="vNumNested"
select="$vposNext - position() - 1"/>
<xsl:copy>
<xsl:copy-of select="@* | node()"/>
<xsl:if test="$vNumNested > 0">
<xsl:copy-of select=
"following-sibling::record
[position() <= $vNumNested]"/>
</xsl:if>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="record[not(@type='normal')]"/>
</xsl:stylesheet>
=====
Cheers,
Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list