How to tell using XPath if an element is present and non empty?
Solution 1
Use:
boolean(//acord:Holding/acord:Policy/acord:PolNumber/text()[1])
this produces true()
if //acord:Holding/acord:Policy/acord:PolNumber
has a first text-node child, and false()
otherwise.
Do note: This is more efficient than counting all text-node children just to compare the count with 0.
Solution 2
You can use boolean(...)
for checking if it's empty, but make sure to look inside the element.
boolean(//PolNumber/node())
This also works if other nodes are contained. If you want to limit to text nodes, replace node()
by text()
. You could want to use //text()
instead, then the query will also yield true for text nodes inside other child elements of <PolNumber/>
.
Solution 3
Maybe I'm a bit late here, but answers are a bit confusing. This one will always returns false when text is blank or with spaces but no chars.
boolean//Holding/Policy/PolNumber/child/text()[normalize-space()]
Solution 4
How about expression="#[?xpath('//acord:Holding/acord:Policy/acord:PolNumber').text != empty]"
? This should work in in all situations
Solution 5
What about using count
to get the number of text nodes:
<expression-filter
expression="#[xpath('count(//Holding/Policy/PolNumber/child::text())') != 0]"/>
Comments
-
Charu Khurana about 4 years
I have an input XML something on this line:
<Holding id="12"> <Policy> <HoldingForm tc="1">Individual</HoldingForm> <PolNumber>848433</PolNumber> <LineOfBusiness tc="1">Life</LineOfBusiness> <CarrierCode>67644</CarrierCode> </Policy> </Holding>
My manipulation on this XML depends on if
<PolNumber>
(its an optional element in schema) has a value or not. I'm using Mule 3.3xpath
evaluator to do this and my XPath expression looks this:<expression-filter expression="#[xpath('//acord:Holding/acord:Policy/acord:PolNumber').text != empty]"/>
This works fine as long as
<PolNumber>
element is present or<PolNumber/>
is empty element. But if<PolNumber>
is absent, above expression throws exception.I tried using XPath boolean function but it returns
true
for<PolNumber/>
. Is there a better way of checking if an element is present and non-empty?EDIT:
This is the configuration of namespace manager in my mule config
<xm:namespace-manager includeConfigNamespaces="true"> <xm:namespace prefix="acord" uri="http://ACORD.org/Standards/Life/2" /> <xm:namespace prefix="soap" uri="http://schemas.xmlsoap.org/soap/encoding/" /> </xm:namespace-manager>
-
Charu Khurana about 11 yearsThank you for your response.
No Such Function {http://www.mulesoft.org/schema/mule/core}:count (org.jaxen.UnresolvableException) org.jaxen.SimpleFunctionContext:127
exception is thrown for count function. -
Charu Khurana about 11 yearsI changed above expression to
<expression-filter expression="#[xpath('fn:count(//acord:Holding/acord:Policy/acord:PolNumber)') != 0]"/>
and that worked, however, for<PolNumber/>
count is non zero just likeboolean
function -
David Dossot about 11 yearsStrange you have to prefix with
fn
. Edit your question and show how is your namespace manager configured please. -
David Dossot about 11 yearsThanks, I think
includeConfigNamespaces
is what's screwing the default namespace and forces to prefix withfn
. Do you really need it? -
David Dossot about 11 yearsI've reviewed by answer to count the number of text child nodes in PolNumber. You may need to prefix with
fn:
in your config. -
Charu Khurana about 11 yearsI don't need
includeConfigNamespaces
attribute really. Removing it caused function to work withoutfn
prefix. Thanks for pointing that. Don't think I'd be able to catch it. -
Charu Khurana about 11 yearsNow, with text child nodes, it works for all the scenarios. Thank you very much
-
Charu Khurana about 11 yearsI agree this is better than counting all text-node children but even this solution is not full-proof. this xpath will return true for
<Holding><Policy><PolNumber></PolNumber><Policy></Holding>
. I don't know how to show a new line in comment but my intent was to have new line character between<PolNumber>
and</PolNumber>
-
Dimitre Novatchev about 11 years@Learner, This is straight-forward:
boolean(//acord:Holding/acord:Policy/acord:PolNumber/text()[normalize-space()][1])
-
Charu Khurana about 11 yearsThanks Dimitre. I don't have exposure with xpath, all this is very helpful to me.
-
JGFMK about 5 yearsThis should have been the accepted answer in my eyes.
boolean(//a/node())
on<a></a>
gives false. Whereas<a><b/></a>
gives true. Try it out here: freeformatter.com/xpath-tester.html.boolean(//a/text()[1])
yields false under both those scenarios.