Davem
Davem

Reputation: 25

XSLT following-sibling output not as expected

I want to get all elements between the first sale and the next sale. Initial XML

<Parent>
    <Sale SeqNo="1"/>
    <Discount SeqNo="2"/>
    <Coupon SeqNo="4"/>
    <CouponDetail SeqNo="5"/>
    <Sale SeqNo="6"/>
    <Sale SeqNo="7"/>
    <Sale SeqNo="8"/>
    <Payment SeqNo="9"/>
</Parent>

Desired XML:

<Discount SeqNo="2"/>
<Coupon SeqNo="4"/>
<CouponDetail SeqNo="5"/>

I currently have the following applying to a template

following-sibling::*[(number(@SeqNo) &lt; number(following::Sale[1]/@SeqNo))]

Output I am currently getting:

<Discount SeqNo="2"/>
<Coupon SeqNo="4"/>
<CouponDetail SeqNo="5"/>
<Sale SeqNo="6"/>
<Sale SeqNo="7"/>
<Sale SeqNo="8"/>
<Payment SeqNo="9"/>

If I hardcode in the sequence number of the next sale item I get the correct output

following-sibling::*[(number(@SeqNo) &lt; number(6))]

Output:

<Discount SeqNo="2"/>
<Coupon SeqNo="4"/>
<CouponDetail SeqNo="5"/>

What am i missing? Any help appreciated.

Upvotes: 1

Views: 67

Answers (1)

Jonathan
Jonathan

Reputation: 113

The issue is the context in which your predicate is being evaluated - it's the particular element child of Parent that is being tested for whether it should be included in the resulting node-set. So in that context, following::Sale[1] gives you the first Sale element following the element being tested, which will always have a higher @SeqNo, even if it is itself a Sale element.

What you need to do is store the sequence number of interest in an xsl:variable prior to doing your select, for instance:

<xsl:variable name="end_seq_no" select="following-sibling::Sale[1]/@SeqNo"/>
<xsl:apply-templates select="following-sibling::*[@SeqNo &lt; $end_seq_no]"/>

Upvotes: 3

Related Questions