I wonder, why this XSLT 1.0 solution doesn't work:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<xsl:template match="a[not(preceding-sibling::*[1][self::a])]">
<a-block>
<xsl:copy-of select="." />
<xsl:apply-templates select="following-sibling::*[1][self::a]" />
</a-block>
</xsl:template>
</xsl:stylesheet>
I have tried to code the sibling-recursion technique for "positional
grouping" suggested by Michael Kay long time ago.
I'll be grateful if anyone let me know what's wrong with the above code.
On 3/9/07, Kolací Tomáš <kolaci(_at_)cncz(_dot_)cz> wrote:
Hi!
I have following input XML:
<root>
<a id="1"/>
<a id="2"/>
<b/>
<d/>
<g/>
<a id="3"/>
<a id="4"/>
<a id="5"/>
<x/>
<a id="6"/>
<a id="7"/>
</root>
and I'm trying to create XSLT 1.0 script, which would nest "uninterrupted"
sibling groups of 'a' elements into 'a-block' elements, so the output would look like:
<root>
<a-block>
<a id="1"/>
<a id="2"/>
</a-block>
<b/>
<d/>
<g/>
<a-block>
<a id="3"/>
<a id="4"/>
<a id="5"/>
</a-block>
<x/>
<a-block>
<a id="6"/>
<a id="7"/>
</a-block>
</root>
How should look XPath selecting next 'a' elements of the same group in template
matching first group element?
I was able to create this (see second xsl:copy-of) (derived from
http://www.biglist.com/lists/xsl-list/archives/200208/msg01182.html idea):
<xsl:template match="a">
<xsl:if test="not(preceding-sibling::*[1][self::a])"> <!-- first node of each
group -->
<xsl:element name="a-block">
<xsl:copy-of select="."/>
<xsl:copy-of select="following-sibling::a
[preceding-sibling::*[1][self::a]]
[generate-id(preceding-sibling::a[not(preceding-sibling::*[1][self::a])][1]) =
generate-id(current())]"/>
<!-- first condition selects only 2nd+ nodes of each group -->
<!-- second condition checks if the 1st node of the group is the current
one -->
</xsl:element>
</xsl:if>
</xsl:template>
and it works (as far as I have test it up to now), but it's ugly, there must be
something simpler..?
Thanks in advance!
Best regards, Tomas Kolaci
____________________
Full script (it does not handle white spaces correctly, but it does not matter
in this case):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="no"/>
<xsl:template match="root">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="a">
<xsl:if test="not(preceding-sibling::*[1][self::a])"> <!-- first node of each
group -->
<xsl:element name="a-block">
<xsl:copy-of select="."/>
<xsl:copy-of select="following-sibling::a
[preceding-sibling::*[1][self::a]]
[generate-id(preceding-sibling::a[not(preceding-sibling::*[1][self::a])][1]) =
generate-id(current())]"/>
<!-- first condition selects only 2nd+ nodes of each group -->
<!-- second condition checks if the 1st node of the group is the current
one -->
</xsl:element>
</xsl:if>
</xsl:template>
<xsl:template match="*">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
--
Regards,
Mukul Gandhi
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--