I need to check if an XML node has at least one non-empty child. Applied to this XML the expression should return true
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
.
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 != '')
<?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="/*/node/*[string-length(text()) >0]!=''"/>
</xsl:template>
</xsl:stylesheet>
Explanation This will find the first node with a string length greater than zero and then compares such node contents with empty string (the comparison will return the existence of a non-empty string node); this code can also be used to look for a specific criteria in any node, for example identify the existence of a node which contains specific string or starts with some character or any other condition; please use this as the inner condition of the node reference for the code to work its magic.
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()]