This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: counting preceding identical elements


Steven,

It's not that position() is "bad practice" -- actually, it can be very good 
practice. The reason it's dangerous is because understanding the way it 
works depends on a good grasp of how parameters like the context node and 
the current node set are determined by the processor. If you don't have 
this deeper grasp of XPath, you'll be left guessing how position() works, 
and you'll usually guess wrong. Yours is a perfect case in point. For example,

count(//section[position()=$section]/preceding::sibling[position()=$slide])

won't give you anything useful, although it's a correctly formed XPath 
location path. Specifically, the step

preceding::sibling[position()=$slide]

looks for all elements named 'sibling' before the context node (of the 
step, which will be a 'section' element), taking only those whose position 
*among the preceding elements named 'sibling', counting in reverse document 
order away from the section* (since the preceding axis is a 'reverse' 
axis), is equal to $slide. That isn't what you want at all. Typing 
"preceding::sibling" when you probably meant "preceding-sibling::slide" is 
part of the problem (not that that's what you want, since I don't think 
your sections have slides as preceding siblings, and even if they did, 
that's not what you want to count). But the way position() works is also 
getting you into trouble.

Now, to how to solve the problem. You say

>What I basically try to do is to calculate the number of preceding slide
>elements of the slide element which position()=$slide and of which the
>parent section element's position()=$section.

As you seem to have surmised, this is much easier to do if your slide is 
the context node, than when it is not. The solution is to go ahead and 
change contexts, for this operation. Changing contexts can be done with an 
xsl:for-each. For example:

<xsl:variable name="absolute-slide-number">
   <xsl:for-each 
select="//section[position()=$section]/slide[position()=$slide]">
     <xsl:value-of select="count(preceding::slide)+1"/>
   </xsl:for-each>
</xsl:variable>

This will give you the count of all slides preceding your target slide, in 
all sections. Is that what you wanted?

<xsl:number> is also another way to go, but it too will require you to 
change your current node. Your efforts in that direction haven't worked 
because you apparently don't know how the 'count' attribute works there (it 
doesn't specify the node whose position you want, but the type of nodes you 
want to count, using a match pattern). Try <xsl:number count="slide" 
level="any"/>.

If I'm guessing wrong about what you need, please post again with a 
clarification of your requirements (maybe a fuller code sample).

Good luck,
Wendell

At 06:21 PM 8/24/01, you wrote:
>Hi,
>
>I am at loss whether what I am trying to do is at all possible. I would be
>able to do it in some other way, but this would mean major rearrangements
>to what I have so far, and I would prefer to keep things the way they are.
>
>I am building a simple Powerpoint-style presentation tool running on top
>of Cocoon.
>
>My XML-structure is simple:
>
><presentation>
>         <info>...</info>
>         <body>
>                 <section>
>                         <slide>...</slide>
>                         <slide>...</slide>
>                         ...
>                 </section>
>                 <section>
>                         yes, same stuff here
>                         ...
>                 </section>
>         </body>
></presentation>
>
>Using Cocoon's clever parameter-passing, I can access each individual
>slide using a section and slide number passed through to the stylesheet,
>using URL's like
>http://localhost/cocoon/presentation/browse?section=2&slide=4
>
>This is all working very nice. Using a main 'presentation' template, I
>build the HTML grid and then <xsl:apply-templates
>select="body/section[position()=$section]/slide[position()=$slide]"/>.
>
>Outside of the node context created by this template however, I want to
>build a little progress indicator showing how far I am in my presentation.
>
>This little portion does most of what I want it to do:
>
>
><b><xsl:value-of select="$section"/></b>
><font size="-1"
>color="gray">/<xsl:value-of select="count(//section)"/></font>&#160;
><font size="+2"><b>|</b></font>&#160;
><font size="-1"><xsl:value-of select="$slide"/>
>         <font color="gray">/
>         <xsl:value-of select="count(//section[position()=$section]/slide)"/>
>         </font>
></font>
>
>builds up a something like this:
>
>2/ 3  |  4/ 6
>
>which is fine, but only depending on the parameters passed into the
>stylesheet ($section and $slide).
>
>The last thing I want to add to the indicator is a percentage - roughly
>calculated by dividing the number of preceding slides by the total amount
>of slides.
>
>And now I fall into problems because this isn't happening when the context
>node 'focus' is on the slide element but outside the main loop.
>
>What I basically try to do is to calculate the number of preceding slide
>elements of the slide element which position()=$slide and of which the
>parent section element's position()=$section.
>
>But I get all kinds of odd numbers - can't really figure out what is
>wrong in my count() argument.
>
>I've been trying
>count(//section[position()=$section]/preceding::sibling[position()=$slide])
>to no avail.
>
>Then I switched strategies into abusing <xsl:number> like:
><xsl:number level="any" count="//section[$section]/slide[$slide]"/>
>but that made not much sense neither.
>
>A long story to ask whether what I am trying to do is really feasible when
>not at the slide element itself but only with the basic knowledge that
>there IS a fourth slide in section 2 due to the parameters.
>
>Any ideas?
>
>I know using position() is considered to be bad practice. Punish me :-)
>
>Regards,
></Steven>
>
>
>  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


======================================================================
Wendell Piez                            mailto:wapiez@mulberrytech.com
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
   Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]