|
Subject: RE: [xsl] Finding sequences of same element From: "Michael Kay" <mike@xxxxxxxxxxxx> Date: Wed, 9 Feb 2005 09:24:40 -0000 |
Search for "positional grouping" for solutions to this problem.
Assuming you want a pure XSLT 1.0 solution, rather than one that relies on
XSLT 2.0 for-each-group, or EXSLT extensions like set:leading(), a recursive
template is probably the simplest approach. In fact, it's sometimes easier
than using for-each-group. Remember that you can use apply-templates as well
as call-template for such problems. Try this:
<xsl:template match="A">
<xsl:copy>
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="A/*" priority="8">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="B[preceding-sibling::*[1][self::B]]" priority="15"/>
<xsl:template match="B" priority="10">
<D>
<xsl:apply-templates select="." mode="sequence"/>
</D>
</xsl:template>
<xsl:template match="B" mode="sequence">
<xsl:copy-of select="."/>
<xsl:apply-templates select="following-sibling::*[1][self::B]"
mode="sequence"/>
</xsl:template>
The way to think about this is that you want to have a template rule for
every element in the result tree, and then you want to organize your
apply-templates to select the nodes in the input tree that will trigger
creation of a node in the result tree.
Michael Kay
http://www.saxonica.com/
> -----Original Message-----
> From: Simon Kissane [mailto:skissane@xxxxxxxxx]
> Sent: 09 February 2005 07:59
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] Finding sequences of same element
>
> Hi
>
> Suppose I have an input document:
> <A><B X="1"/><B X="2"/><B X="3"/><C X="4"/><B X="5"/><B
> X="6"/><B X="7"/></A>
>
> Now, suppose I wish to group together consecutive B elements, giving a
> result document like this:
> <A><D><B X="1"/><B X="2"/><B X="3"/></D><C X="4"/><D><B X="5"/><B
> X="6"/><B X="7"/></D></A>
>
> How can I do this? (I would prefer not to use recursive templates, but
> rather for-each, if that is at all possible...)
>
> I think I can find the initial element of these sequences, like so:
> B[not(preceding-sibling::*) or
> preceding-sibling::*[0][not(self::B)]]
> This, I think, should select all B for which there are either no
> preceeding sibling elements, or for which the immediately preceeding
> sibling element is not a B element. Thus, in the above example, it
> would pick B[@X=1] and B[@X=5].
>
> But, given each initial sequence element, how can I find the remaining
> nodes in the sequence? With the initial sequence element as the
> context node, I could do:
> .|following-sibling::B
> But that will also pick up B[@X=5] and B[@X=6] when the
> context node is B[@X=1].
>
> Is there a predicate test I could use on following-sibling::B to
> restrict it only to the current sequence of B elements?
>
> Thanks
>
> Simon Kissane
| Current Thread |
|---|
|
| <- Previous | Index | Next -> |
|---|---|---|
| Re: [xsl] Finding sequences of same, Mukul Gandhi | Thread | Re: [xsl] Finding sequences of same, Dimitre Novatchev |
| RE: [xsl] Can I use a boolean varia, Michael Kay | Date | [xsl] Addressing siblings, David.McKay |
| Month |