Subject: Re: counter From: Jeni Tennison <Jeni.Tennison@xxxxxxxxxxxxxxxx> Date: Wed, 21 Jun 2000 17:23:22 +0100 |
Nick, >Kay Michael wrote: >The way to print something every fifty <item> elements is: >> >> <xsl:template match="item[position() mod 50 = 1]"> >> <fifty-items> >> Here's the next 50: >> <xsl:for-each select=". | following-sibling::item[position() < 50]"> >> <item><xsl:value-of select="."/></item> >> </xsl:for-each> >> </fifty-items> >> </xsl:template> > >Having tried this solution and some variations I had a couple of questions (I >presume that this template was called by <xsl:apply-templates select="item">) > >a. I found that when running this I was getting the item content repeated in >the ouput for each element where the expression in the template match >attribute was false. I put this down to a built-in template being called for >those elements, is this correct ? That's right. The built-in templates include: <xsl:template match="*|/"> <xsl:apply-templates/> </xsl:template> which steps through the document, processing the root node, the document element, and its descedents, including its content and: <xsl:template match="text()|@*"> <xsl:value-of select="."/> </xsl:template> which matches any text that's found (or attribute values) and gives the value of that text. When you only want to process some particular elements, but the elements that you *don't* want to process contain text, you have to make sure that you are processing only the elements you *do* want to process. You can do this in three ways: 1. move the filtering XPath from the 'match' attribute of the xsl:template to the 'select' attribute of the xsl:apply-template that calls it (as you have done): <xsl:template match="root"> <xsl:apply-templates select="item[position() mod $cntr = 1]"/> </xsl:template> <xsl:template match="item"> <xsl:for-each select=". | following-sibling::item[position() < $cntr]"> Item <xsl:value-of select="."/> </xsl:for-each> </xsl:template> 2. put the content of the xsl:template within an xsl:if that tests on the filter that you're using, and change the templates to match all (wanted and not wanted) elements, so something like: <xsl:template match="item"> <xsl:if test="position() mod $cntr = 1"> <xsl:for-each select=". | following-sibling::item[position() < $cntr]"> Item <xsl:value-of select="."/> </xsl:for-each> </xsl:if> </xsl:template> 3. add a mode to the template and make sure that the xsl:apply-templates that calls it only calls templates in that mode, so something like: <xsl:template match="root"> <xsl:apply-templates mode="grouped" /> </xsl:template> <xsl:template match="item[position() mod $cntr = 1]" mode="grouped"> <xsl:for-each select=". | following-sibling::item[position() < $cntr]"> Item <xsl:value-of select="."/> </xsl:for-each> </xsl:template> >However I did notice a significant >performance improvement over Mike's code which was disproportionate to the >number of item elements in the source document. Mike will be able to tell you better than I can about this, but I suspect that it's because in the original code, the items that were not picked up by your template were first processed by the built-in template for elements, and then their content processed by the built-in template for text, before outputting the value of the item. Searching for templates takes time, so filtering down the nodes that you have to search for templates that match on benefits you, as does using <xsl:value-of select="." /> rather than <xsl:apply-templates /> when you know that the content of an element is just text [1]. Based on that, Options 1 and 3, which both filter within the xsl:apply-templates are probably better than Option 2 in most cases. Cheers, Jeni [1] #8 of Mike's Eight tips for how to write efficient XSLT at http://www.mulberrytech.com/xsl/xsl-list/archive/msg13316.html XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: counter, Mike Brown | Thread | RE: counter, dave . challis |
Re: counter, Mike Brown | Date | Re: xsl:key, David_Marston |
Month |