Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to count the number of same immediate preceding siblings in xsl

Tags:

xslt

xslt-2.0

I'm using xslt version 2, I'm trying to transform an xml to a fo output, and I'm stuck on a specific problematic.

Here is what looks like my input:

    <a1/>
    <a1/>
    <b/>
    <c/>
    <d/>
    <a2/>
    <b/>
    <c/>
    <a1/>
    <a1/>
    <a1/>
    <a1/>
    <b/>
    <c/>
    <d/>

This data, functionally speaking, contains a list of 'sets' defined by a1|a2,b?,c?,d?.

My problem is that I don't see how I can count the number of a1 tags for a specific 'set'.

Indeed, I have written my xsl and I get an output like that:

<fo:table>
    <fo:row>
        <fo:cell>b: </fo:cell>
        <fo:cell>b value</fo:cell>
    </fo:row>
    <fo:row>
        <fo:cell>a1: </fo:cell>
        <fo:cell>number of a1 ???</fo:cell> <-- what I am trying to retrieve
    </fo:row>
    <fo:row>
        ...
    </fo:row>
    ...
</fo:table>

I have done an apply-template on a1+|a2 tags, and I do nothing if a1 tag has a following sibling that equals to a1. I think there must be a way to count the tags with preceding sibling (but then how to insure to count only the corresponding one?)

Any hints would be appreciated!

Edit: On the above example of input, the first count should be 2:

    <a1/>
    <a1/>
    <b/>
    <c/>
    <d/>

then it should be 4, and not 6:

    <a1/>
    <a1/>
    <a1/>
    <a1/>
    <b/>
    <c/>
    <d/>
like image 810
skoll Avatar asked Dec 16 '22 08:12

skoll


1 Answers

Your question is not really clear.
What should "the corresponding one" be? Counting all a1 before the current one would be:

 count(preceding-sibling::a1) 

if needed you may add predicates like:

 count(preceding-sibling::a1[/corresponding one/]) 

To count only the presiding sibling a1 which are in a sequence of a1 nodes try this: Find the first node which is not an a1.

<xsl:variable name="firstnota1" select="preceding-sibling::*[not (self::a1)][1]" />

The wonted result than, is count all nodes before the current a1 minus the count of nodes before the first not a1 + this node it self.

<xsl:value-of select="count(preceding-sibling::*) 
       -  count($firstnota1/preceding-sibling::* | $firstnota1)"/>

Or without variable:

<xsl:value-of 
      select="count(preceding-sibling::*)
             -  count( preceding-sibling::*[not (self::a1)][1]
                      /preceding-sibling::*
                      | preceding-sibling::*[not (self::a1)][1] )"/>
like image 92
hr_117 Avatar answered Apr 27 '23 17:04

hr_117