Search code examples
saxonxslt-3.0

XSLT 3.0 Streaming (Saxon) facing error "There is more than one consuming operand" when I use two different string functions within same template


Here is my sample input xml

<?xml version="1.0" encoding="UTF-8"?>
<Update xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Request>
<List>
<RequestP><ManNumber>3B4</ManNumber></RequestP>
<RequestP><ManNumber>8T7_BE</ManNumber></RequestP>
<RequestP><ManNumber>3B5</ManNumber></RequestP>
<RequestP><ManNumber>5E9_BE</ManNumber></RequestP>
<RequestP><ManNumber>9X6</ManNumber></RequestP>
</List>
</Request>
</Update>

and xslt

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="3.0" exclude-result-prefixes="#all">
   <xsl:output method="xml" omit-xml-declaration="no" indent="yes" />
   <xsl:mode streamable="yes" />
    <xsl:template match="List/RequestP/ManNumber">
            <ManNumber>
               <xsl:value-of select="replace(.,'_BE','')" />
            </ManNumber>  
        <xsl:if test="contains(.,'_BE')">
         <ManDescrip>BE</ManDescrip>
        </xsl:if>
   </xsl:template>
   </xsl:stylesheet>

I am getting below error for above xslt, I am using Saxon 11.2 version

Template rule is not streamable
  * There is more than one consuming operand: {<ManNumber {xsl:value-of}/>} on line 6, and {if(fn:contains(...)) then ... else ...} on line 9

The xslt works fine if I use either "replace" or "contains" but not both within same template.


Solution

  • Streamed processing, if you have needs (huge input documents in the size of gigabytes) to use it, requires you to limit your XSLT to streamable code, that means you can for instance make a copy of that element and processed only that small element node as a complete in memory element in a different mode

    <xsl:template match="List/RequestP/ManNumber">
      <xsl:apply-templates select="copy-of(.)" mode="grounded"/>    
    </xsl:template>
    
    <xsl:template name="grounded" match="ManNumber">
       <ManNumber>
               <xsl:value-of select="replace(.,'_BE','')" />
        </ManNumber>  
        <xsl:if test="contains(.,'_BE')">
         <ManDescrip>BE</ManDescrip>
        </xsl:if>
    </xsl:template>