|
Subject: [xsl] XPath selecting chain of following siblings of the same name From: Kolací Tomáš <kolaci@xxxxxxx> Date: Fri, 9 Mar 2007 14:29:29 +0100 |
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>
| Current Thread |
|---|
|
| <- Previous | Index | Next -> |
|---|---|---|
| Re: [xsl] xsl:number from="/" level, Deborah Pickett | Thread | Re: [xsl] XPath selecting chain of , Martin Honnen |
| Re: [xsl] Schema-aware validation o, David Carlisle | Date | Re: [xsl] Schema-aware validation o, Jesper Tverskov |
| Month |