This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: position() returning incorrect results
- From: jon wa <jonni at gmx dot co dot uk>
- To: xsl-list at lists dot mulberrytech dot com
- Cc: xsl-list at lists dot mulberrytech dot com
- Date: Thu, 14 Feb 2002 18:12:12 +0100 (MET)
- Subject: Re: [xsl] position() returning incorrect results
- References: <0437034752.20020214155442@jenitennison.com>
- Reply-to: xsl-list at lists dot mulberrytech dot com
ah! damn whitespace :)
Thanks Jeni, i was loosing it there for a minute ;)
> Hi Jon,
>
> > i just had an <xsl:apply-templates> to get the stylesheet to work on
> > an html like file, which just had lots of <p> tags for paragraphs in
> > it. when i do the <xsl:template match="p"> and then try to print the
> > position() it all goes wrong and seems to count up in twos. what
> > confuses me more is that if i have a seperate template for
> > <xsl:template match="p[1]"> it will correctly pick out the first
> > paragraph and report it's position() as being 1.
>
> Yep, this is because the way position() works within a template is
> different from the way position() works within a pattern.
>
> Within a pattern (in a match attribute), you actually test the
> position of a node amongst its siblings that are the same type as that
> node. So your pattern of p[1] gives you a template that matches the p
> elements that are the first p element children of their parent
> elements. It would match a p element whose only preceding sibling was
> a comment, or a text node, or a ul element.
>
> Within a template, on the other hand, the position() function gives
> you the position of the node that you're processing with that template
> within the list of nodes that are currently being processed. That
> means that the position() of a node according to a template depends on
> the xsl:apply-templates that's used to apply the template. If, as is
> frequently the case, you use:
>
> <xsl:apply-templates />
>
> then the position() of the node will be the position of the node
> amongst all its sibling nodes.
>
> "But," I hear you wonder "the p elements that I'm applying templates
> to are the only children of their parent element anyway, so surely the
> first p element should have the position 1?"
>
> And the answer would be "yes" if that were the case. But usually, and
> I'm guessing in your case, the elements actually have invisible
> siblings -- whitespace-only text nodes! Take the example:
>
> <div>
> <p>...</p>
> <p>...</p>
> </div>
>
> The div element actually has five children - a whitespace-only text
> node (giving a line break and some indentation), the first p element,
> another whitespace-only text node, the second p element, and a final
> whitespace-only text node.
>
> There are two solutions to this predicament. The first solution is to
> only select the p elements when you apply templates:
>
> <xsl:apply-templates select="p" />
>
> That way the node set only contains the nodes that you actually want
> to count.
>
> The second solution is to strip out those pesky whitespace-only text
> nodes from the node tree, so that they're not counted anyway. You can
> do this by placing a xsl:strip-spaces directive at the top of your
> stylesheet. When I'm processing data-oriented XML (which doesn't
> include mixed content), I usually use:
>
> <xsl:strip-space elements="*" />
>
> To strip whitespace-only text nodes from all the elements in the
> document. You might want to be more careful, and only strip the
> whitespace-only text nodes from (say) the body and div elements, with:
>
> <xsl:strip-space elements="body div" />
>
> I hope that helps,
>
> Jeni
>
> ---
> Jeni Tennison
> http://www.jenitennison.com/
>
>
> XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
>
--
GMX - Die Kommunikationsplattform im Internet.
http://www.gmx.net
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list