Charu Khurana
Charu Khurana

Reputation: 4551

How to tell using XPath if an element is present and non empty?

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.3 xpath 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>

Upvotes: 22

Views: 82891

Answers (5)

Thomas Modeneis
Thomas Modeneis

Reputation: 697

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()]

Upvotes: 3

user3190499
user3190499

Reputation: 61

How about expression="#[?xpath('//acord:Holding/acord:Policy/acord:PolNumber').text != empty]" ? This should work in in all situations

Upvotes: 2

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243459

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.

Upvotes: 31

Jens Erat
Jens Erat

Reputation: 38662

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/>.

Upvotes: 13

David Dossot
David Dossot

Reputation: 33413

What about using count to get the number of text nodes:

<expression-filter
    expression="#[xpath('count(//Holding/Policy/PolNumber/child::text())') != 0]"/>

Upvotes: 2

Related Questions