[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] counting with position()


Subject: Re: [xsl] counting with position()
From: a kusa <akusa8@xxxxxxxxx>
Date: Tue, 5 Jan 2010 16:12:59 -0600

Thanks for your response.

The reason that I am testing if there is no following-sibling is
because there could be nested lists with product elements and I dont
want to match those.
So my input can look like this:

<level1>
<item>Sample</item>
<product>sample prod1</product>
<product>sample prod2</product>
        <level2>
<item>Sample</item>
<product>sample prod11</product>
<product>sample prod12</product>
<product>sample prod13</product>
              <level3>
                 <item>Sample</item>
<product>sample prod14</product>

                 <item>Sample</item>
               </level3>
<item>Sample</item>
<product>sample prod15</product>
<product>sample prod16</product>
<item>Sample</item>
<level3>
<item>Sample</item>
</level3>
<product>sample prod17</product>

         </level2>
<level1>

I only want to match sample prod1 and sample prod2 after <item> at level1.

You are right. My count is cutting out the last product which is NOT
what I intend. I want all product1 and 2 until the start of level2.


On Tue, Jan 5, 2010 at 3:34 PM, Imsieke, Gerrit, le-tex
<gerrit.imsieke@xxxxxxxxx> wrote:
> Isn't that overly complicated, in general?
>
> And is this actual code that outputs 1 product element as you stated?
>> <xsl:template match="level2">
>> <xsl:if
>>
test="following-sibling::*[1][self::product[preceding-sibling::*[1][self::ite
m]
> There is no following-sibling to level2. Maybe you intended to match
> level2/item and test some conditions about its following-siblings. Then
your
> level2 template should copy level2 and apply-templates to ./item only. But
> this code still won't yield the quoted results.
>
> I'm trying to guess what you want to achieve from this inner code.
>>                                        <xsl:variable name="count"
>> select="count(./following-sibling::product[position()!=last()])"/>
>>                                        <xsl:if test="$count>= 1">
>>                                                <xsl:apply-templates
>> select="./following-sibling::product[position() &lt; $count]"/>
>>                                        </xsl:if>
>
> Is it:
> - $count is set to the number of products after item (not counting the last
> product though). In your case it should be 2.
> - If count is greater than or equal to 1, then the products whose
position()
> is less than $count should be subject to apply-templates. In your example,
> this will be the first product.
> ?
>
> This may be achieved by this snippet:
>
>  <xsl:template
>    match="level2/product[
>             preceding-sibling::item
>             and
>             (: All products before this one but after the
>                immediately precedent item must also be products:)
>             (
>               every $p in preceding-sibling::*[
>                 . &gt;&gt; preceding-sibling::item[1]
>               ] satisfies $p/self::product
>             )
>             and
>             (: All following siblings before level3 must also be
>                products.  If there's no level3 then the every
>                expression evals to true() :)
>             (
>               every $f in following-sibling::*[
>                 . &lt;&lt; following-sibling::level3[1]
>               ] satisfies $f/self::product
>             )
>           ][
>             (: Restrict the result so far to all but the last
>                two items - don't know if this is really what you want:)
>             position() lt last() - 1
>           ]
>           ">
>    <!-- Really only apply, not copy? -->
>    <xsl:apply-templates />
>  </xsl:template>
>
>  <!-- Discard all other products: -->
>  <xsl:template match="level2/product" priority="0"/>
>
>  <!-- Everything else: identity -->
>  <xsl:template match="@* | *" priority="-1">
>    <xsl:copy>
>      <xsl:apply-templates select="@* | * | text()" mode="#current" />
>    </xsl:copy>
>  </xsl:template>
>
>
> But maybe you are looking for an xsl:for-each-group
> group-starting-with="item|level3", and then look at current-group()[1]
> whether it's item, and then process the rest of current-group() if it
> consists of products only?
>
> Gerrit


Current Thread