June 25, 2009

Check for and remove empty nodes in XSLT

On one of our projects, we use AIA canonicals extensively, and for those familiar with them, their definition is quite large. At times, our payloads were over 1.5MB because all elements, including empty ones, were mapped to the final message.

One way to work around this is to create a transformation to remove the empty nodes.

For example, your process may have 5 input elements and 5 result elements. Your transformation may merely copy each input element to it's corresponding output element as shown here:
    <xsl:template match="/">
    <ns1:EmptyNodesTestProcessResponse>
    <ns1:result1>
    <xsl:value-of select="/ns1:EmptyNodesTestProcessRequest/ns1:input1"/>
    </ns1:result1>
    <ns1:result2>
    <xsl:value-of select="/ns1:EmptyNodesTestProcessRequest/ns1:input2"/>
    </ns1:result2>
    <ns1:result3>
    <xsl:value-of select="/ns1:EmptyNodesTestProcessRequest/ns1:input3"/>
    </ns1:result3>
    <ns1:result4>
    <xsl:value-of select="/ns1:EmptyNodesTestProcessRequest/ns1:input4"/>
    </ns1:result4>
    <ns1:result5>
    <xsl:value-of select="/ns1:EmptyNodesTestProcessRequest/ns1:input5"/>
    </ns1:result5>
    </ns1:EmptyNodesTestProcessResponse>
    </xsl:template>
However, during execution, if an input element is empty or non-existent, it will still map as 'blank' to the output element. For example, if there is no data for input3, the result is still returned as follows:
    <ns1:result3/>
As XSDs are larger in size, this becomes more of a size concern.

To work around this, create a transformation that has a source and target variable of your output variable. In this, add the following:
    <xsl:template match="@*|node()">
    <xsl:if test=". != '' or ./@* != ''">
    <xsl:copy>
    <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
    </xsl:if>
    </xsl:template>
As you can see from the execution below, the first transformation essentially copied all input elements to their corresponding output result element, including the blank element result3. However, by applying a second transformation, all empty nodes are removed.

4 comments: