Home > Mobile >  Xpath: Check if node doesn't exist
Xpath: Check if node doesn't exist

Time:07-01

I get the XML from my webshops API call structured much like the example below:

<Customers>
<Customer>
    <Username>userOne</Username>
    <Params>
        <Param>
            <Id>111</Id>
            <Name>Param1</Name>
            <Value><![CDATA[Param 1 is on]]></Value>
        </Param>
        <Param>
            <Id>112</Id>
            <Name>Param2</Name>
            <Value><![CDATA[OFF]]></Value>
        </Param>
    </Params>
</Customer>
<Customer>
    <Username>userTwo</Username>
    <Params>
        <Param>
            <Id>111</Id>
            <Name>Param1</Name>
            <Value><![CDATA[Param 1 is on]]></Value>
        </Param>
        <Param>
            <Id>112</Id>
            <Name>Param2</Name>
            <Value><![CDATA[OFF]]></Value>
        </Param>
    </Params>
</Customer>
<Customer>
    <Username>userThree</Username>
    <Params>            
        <Param>
            <Id>112</Id>
            <Name>Param2</Name>
            <Value><![CDATA[ON]]></Value>
        </Param>
    </Params>
</Customer>

There are way more parameters in them, ans the amount varies dependong on many outside factors. I'm trying to get the usernames for when the values for id"111" and id"112" are what I'm looking for. Customers/Customer[Params/Param[Id/text()='111']/Value/text()='Param 1 is on'][Params/Param[Id/text()='112']/Value/text()='OFF']/Username/text()

The above code returns "userOne" and "userTwo" as expected.

The problem is, that Id"111" either has the value "Param 1 is on" or nothing, and if it has no value it won't show up in the XML. So I need an expression that checks if a node with id"111" doesn't exist and the value of id"112" is "ON".

Xpath is realy new to me unfortunatelly, and I couldn't find a way to check specificly if a node doesn't exist.

CodePudding user response:

XPath count(expr)can be used to check the absence of a condition

Customers/Customer[count(Params/Param[Id/text()='111' and Value/text()='Param 1 is on']) = 0 and Params/Param[Id/text()='112']/Value/text()='ON']/Username/text()

So this part checks that that node does not exist
count(Params/Param[Id/text()='111' and Value/text()='Param 1 is on']) = 0
or
count(Params/Param[Id/text()='111']) = 0

AND this part checks the other expected condition
Params/Param[Id/text()='112']/Value/text()='ON'

Applied on the sample returns:
userThree

CodePudding user response:

Per definition a nodeset, when cast to boolean is true and only true if it has elements (https://www.w3.org/TR/xpath-31/#dt-ebv). With that an existence check for the value element can look like

fn:boolean(Customers/Customer[Params/Param[Id/text()='111']/Value)

or if you want to include that in your check as a third alternative

Customers/Customer[Params/Param[Id/text()='111' and not ./Value]
  • Related