Home > database >  How to use an accumulator in XSLT 3.0?
How to use an accumulator in XSLT 3.0?

Time:09-26

What is wrong with my codes? It says:

"Accumulator figNum is not applicable to the current document"

Here is the XML:

<?xml version="1.0" encoding="UTF-8"?>
<book>
   <chapter>
      <figure/>   
      <figure/>
      <figure/>   
   </chapter>
   <chapter>
      <figure/>   
      <figure/>
      <figure/>   
   </chapter>
   <chapter>
      <figure/>   
      <figure/>
      <figure/>   
   </chapter>
</book>

Here is the XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" 
     xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:accumulator name="figNum" as="xs:integer" initial-value="0">
      <xsl:accumulator-rule match="chapter" select="0"/>
      <xsl:accumulator-rule match="figure" select="$value 1"/>
   </xsl:accumulator>
   <xsl:mode />

   <xsl:template match="book">
     <xsl:apply-templates/>
     <p>Figure <xsl:value-of select="accumulator-before('figNum')" />
     </p>
   </xsl:template>  
</xsl:stylesheet>

CodePudding user response:

You need to explicitly apply an accumulator with e.g. xsl:mode use-accumulators="figNum"; additionally I think, given your sample, using the following makes more sense as an example:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" 
     xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     exclude-result-prefixes="#all">
  
   <xsl:accumulator name="figNum" as="xs:integer" initial-value="0">
      <xsl:accumulator-rule match="chapter" select="0"/>
      <xsl:accumulator-rule match="figure" select="$value 1"/>
   </xsl:accumulator>

   <xsl:mode use-accumulators="figNum"/>

   <xsl:template match="chapter">
     <xsl:apply-templates/>
     <p>Figures <xsl:value-of select="accumulator-after('figNum')" />
     </p>
   </xsl:template>  
   
</xsl:stylesheet>

Or perhaps, to use both accumulator-before and accumulator-after:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" 
     xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     expand-text="yes"
     exclude-result-prefixes="#all">
  
   <xsl:accumulator name="chapterNum" as="xs:integer" initial-value="0">
      <xsl:accumulator-rule match="chapter" select="$value 1"/>
   </xsl:accumulator>
  
   <xsl:accumulator name="figNum" as="xs:integer" initial-value="0">
      <xsl:accumulator-rule match="chapter" select="0"/>
      <xsl:accumulator-rule match="figure" select="$value 1"/>
   </xsl:accumulator>

   <xsl:mode on-no-match="shallow-copy" use-accumulators="#all"/>

   <xsl:template match="figure ">
     <xsl:comment>{local-name()} {accumulator-before('figNum')} in {local-name(..)} {accumulator-before('chapterNum')}</xsl:comment>
     <xsl:next-match/>
   </xsl:template> 
   
   <xsl:template match="chapter">
     <xsl:comment>{local-name()} {accumulator-before('chapterNum')}</xsl:comment>
     <xsl:next-match/>
     <p>Figures in {local-name()} {accumulator-before('chapterNum')}: {accumulator-after('figNum')}</p>
   </xsl:template> 
   
   <xsl:output indent="yes"/>
   
</xsl:stylesheet>
  • Related