Search code examples
xmlxsltxslt-3.0

xslt3.0 - accumulator is not getting updated with blank value


Input XML:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <Entry>
        <Tag1>A1</Tag1>
        <Tag2>B1</Tag2>
    </Entry>
    <Entry>
        <Tag1>A2</Tag1>
        <Tag2/>
    </Entry>
</Root>

XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="3.0">
    
    <xsl:output method="text"/>
    
    <xsl:mode on-no-match="shallow-skip" streamable="yes" use-accumulators="#all"/>
    
    <xsl:accumulator name="Tag2" as="xs:string"
        initial-value="''" streamable="yes">
        <xsl:accumulator-rule match="Tag2/text()" 
            select="." />
    </xsl:accumulator>
    
    <xsl:template match="/*" expand-text="yes">
        <xsl:apply-templates/>
        Tag2 {accumulator-after('Tag2')}
    </xsl:template>
    
</xsl:stylesheet>

Output:

    Tag2 B1

I am expecting the output as Tag2 <<empty>> as the 2nd element does not have value defined against Tag2.

Is there anyway we can check and make sure accumulator considers the cases when there is no value against the node?


Solution

  • You match on text() nodes, there is no text node in an empty element.

    Add a rule matching the element that sets the value to the empty string:

    <xsl:accumulator name="Tag2" as="xs:string"
        initial-value="''" streamable="yes">
        <xsl:accumulator-rule match="Tag2" select="''"/>
        <xsl:accumulator-rule match="Tag2/text()" 
            select="." />
    </xsl:accumulator>