XSL / XPath expression to check if a node contains at least one non-empty child
Solution 1
More accurate, simpler and more efficient (no need to use the count()
function):
/*/node/*[text()]
If you want to exclude any element that has only whitespace-only text children, use:
/*/node/*[normalize-space()]
Solution 2
You just need <xsl:if test="/xml/node/* != ''" />
.
In XPath an =
or !=
comparison where one side is a node set and the other side is a string succeeds if any of the nodes in the set passes the comparison. Thus
not(x = '')
means "it is not the case that any x
child element of the current node has an empty string value", which is fundamentally different from
x != ''
which means "at least one x
child element of the current node has a string value that is not empty". In particular, if you want to check that all x
children are empty, you need to use a "double-negative" test
not(x != '')
Solution 3
Here's one XPath that should accomplish the job:
count(/*/node/*[text()]) > 0
When used in a sample XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:value-of select="count(/*/node/*[text()]) > 0" />
</xsl:template>
</xsl:stylesheet>
...which is, in turn, applied to the provided example XML:
<xml>
<node>
<node1/>
<node2/>
<node3>value</node3>
</node>
</xml>
...the expected result is produced:
true
If we apply the same XSLT against a simply modified XML:
<xml>
<node>
<node1/>
<node2/>
<node3/>
</node>
</xml>
...again, the expected result is produced:
false
Explanation:
The XPath used searches for all children of a <node>
element (which are, in turn, children of the root element) that have a non-empty text value (as specified by text()
); should the count of such <node>
children be greater than 0, then the XPath resolves to true
.
Comments
-
svz almost 4 years
I need to check if an XML node has at least one non-empty child. Applied to this XML the expression should return
true
<xml> <node> <node1/> <node2/> <node3>value</node3> </node> </xml>
I tried to use this expression:
<xsl:if test="not(/xml/node/child::* = '')">
but it seems to check if all children are not empty.How can I write an expression which returns
true
if at least one element is not empty? Is there a way to do this without creating another template to iterate over node chldren?UPD: I'm thinking of counting non-empty nodes like
test="count(not(/xml/node/child::* = '')) > '0'"
but somehow just can't make it work right. This expression is not a well-formed one.