I'm trying to sum up a set of values in an XML using XSLT and XPath function fn:sum. This works fine as long as the values are non-null, however this is not the case. To illustrate my problem I've made an example:
<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:template match="/root">
<root>
<!-- Works fine for non-null values -->
<sum><xsl:value-of select="fn:sum(values/value)" /></sum>
</root>
</xsl:template>
</xsl:stylesheet>
and the XML:
<?xml version="1.0"?>
<root>
<values>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
<!-- Nullvalue -->
<value />
</values>
</root>
The example works fine as long as there's no null-values. I've tried various variants of the select, such as <xsl:value-of select="fn:sum(values[value != '']/value)" />
(as you might notice, not much of an XSLT export ;) ) How can I filter out the null-values?
exsl:node-set() XSLT/XPath Reference: XSLT elements, EXSLT functions, XPath functions, XPath axes. exsl:node-set() returns a node-set from a result tree fragment, which is what you get when you look at the xsl:variable instead of its select attribute to fetch a variable's value.
XSLT <xsl:text> The <xsl:text> element is used to write literal text to the output. Tip: This element may contain literal text, entity references, and #PCDATA.
XSLT 2.0's Regular Expression Instructions. In addition to letting you describe patterns and then finding out if they exist in text, regular expression support in a language like Perl lets you find out exactly what text matched that pattern, and you can then use that text in your program logic.
Explicitly test that the nodes have content:
<sum><xsl:value-of select="fn:sum(values/value[text()])" /></sum>
I think that what you mentioned:
<xsl:value-of select="fn:sum(values[value != '']/value)" />
does not work, because the node is empty - it does not contain a text node at all, whereas value != ''
tests for an empty string - that is, a text node having data of length 0.
To sum just the elements that contain numbers:
<sum>
<xsl:value-of select="fn:sum(values/value[number(.)=number(.)])" />
</sum>
The result of number()
will be NaN
for empty elements, or elements whose string value is not a number.
MSDN reference - http://msdn.microsoft.com/en-us/library/ms256211.aspx
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With