Subject: Re: [xsl] position() returning incorrect results From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Thu, 14 Feb 2002 15:54:42 +0000 |
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
Current Thread |
---|
<- Previous | Index | Next -> |
---|---|---|
[xsl] position() returning incorrec, jon wa | Thread | Re: [xsl] position() returning inco, jon wa |
RE: [xsl] how to select the same at, Oliver Becker | Date | [xsl] How to use xsl:key and xsl:so, Uslu, Cihan Y (MED) |
Month |