Subject: Re: [xsl] Using an empty xsl:for-each statement to "touch" elements From: Michael Kay <mike@xxxxxxxxxxxx> Date: Thu, 12 Dec 2013 11:01:39 +0000 |
The way the spec is written (I'll go on to the Saxon implementation later) you shouldn't need to "touch" the elements. Looking at the draft here: http://www.w3.org/TR/2013/WD-xslt-30-20131212/ You should be able to do > <xsl:template match="purchase-order"> > <Total-Cost> > <xsl:value-of select="accumulator-after('f:item-cost')"/> > </Total-Cost> > </xsl:template> which is the equivalent of > <xsl:template match="purchase-order"> > <Total-Cost> > <xsl:value-of select="f:total-item-cost()"/> > </Total-Cost> > </xsl:template> in the 2012 draft. The reason this works is that the xsl:value-of qualifies as both a pre-descent and a post-descent instruction, because it has no consuming instruction as either a preceding or a following sibling. I dare say this almost certainly doesn't work in Saxon 9.5, where as you suggest you will probably have to inject a consuming instruction into the template before you can get the post-descent value of the accumulator. You could for example write <xsl:sequence select="nothing"/>. Michael Kay Saxonica On 12 Dec 2013, at 10:40, Costello, Roger L. <costello@xxxxxxxxx> wrote: > Hi Folks, > > Suppose you want to add together all the costs in this purchase order: > > <purchase-order> > <item> > <cost>10</cost> > </item> > <item> > <cost>20</cost> > </item> > <item> > <cost>19</cost> > </item> > <item> > <cost>25</cost> > </item> > <item> > <cost>17</cost> > </item> > </purchase-order> > > The new XSLT 3.0 accumulator can be used. The accumulator is updated each time a <cost> element is "touched". To "touch" each <cost> element I have this empty loop: > > <xsl:for-each select="item"> > <xsl:for-each select="cost"/> > </xsl:for-each> > > That inner loop doesn't need any statements because its sole purpose is merely to "touch" the cost element, and thereby trigger the accumulator to be updated. > > Here is the XSLT program with the accumulator: > > <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > xmlns:xs="http://www.w3.org/2001/XMLSchema" > exclude-result-prefixes="#all" > version="3.0"> > > <xsl:output method="xml" /> > > <xsl:accumulator name="f:item-cost" > post-descent="f:total-item-cost" > as="xs:integer" > initial-value="0"> > <xsl:accumulator-rule match="cost" new-value="$value + xs:integer(.)"/> > </xsl:accumulator> > > <xsl:template match="purchase-order"> > <Total-Cost> > <xsl:for-each select="item"> > <xsl:for-each select="cost"/> > </xsl:for-each> > <xsl:value-of select="f:total-item-cost()" /> > </Total-Cost> > </xsl:template> > > </xsl:stylesheet> > > I realize that this problem could be solved in other ways, but I wanted to show how it could be solved using an accumulator. And that invariably led me to an empty xsl:for-each statement. > > Is there a better way to "touch" an element than using an empty xsl:for-each statement? > > /Roger
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Using an empty xsl:for-each s, Costello, Roger L. | Thread | [xsl] Efficient way to do an identi, Costello, Roger L. |
[xsl] Using an empty xsl:for-each s, Costello, Roger L. | Date | [xsl] Efficient way to do an identi, Costello, Roger L. |
Month |