0

How can I fetch IDs with condition name="task1", value="abc" AND name="task2", value="efg" name="task5", value="nop"

Expected Output: ABC-123; XYZ-987
Actual Output: XYZ-987
Query: /node1/node2/node3[condition/task[@name='task1' and @value='abc'] and condition/task[@name='task2' and @value='efg'] and condition/task[@name='task5' and @value='nop'] and count(condition/task)=3]/id

Query Referred from How to parse and fetch exact result from XML using XPATH

Catch if all the operation in tasks, other than satisfied tasks, are "OR" then that ID should also be considered as a satisfied condition. In the XML below, ABC-123, LMN-543 and XYZ-987 satisfy the condition but ABC-123 has all other operation="OR". So this should also be included in the result. By using count, I restrict to 3 tasks so ABC-123 is not included. Using count>3 will fetch ABC-123, LMN-543 and XYZ-9876.

Need Output as ABC-123; XYZ-987 using condition check on operation=or

Following is the XML used

<node1>
<node2>
    <node3>
        <id>ABC-123</id>
        <condition>
            <task name="task1" operation="and" value="abc" />
            <task name="task2" operation="and" value="efg" />
            <task name="task3" operation="or" value="hij" />
            <task name="task4" operation="or" value="klm" />
            <task name="task5" operation="or" value="nop" />
            <task name="task6" value="uvw" />
        </condition>
    </node3>
    <node3>
        <id>LMN-543</id>
        <condition>
            <task name="task1" operation="and" value="abc" />
            <task name="task2" operation="and" value="efg" />
            <task name="task3" operation="and" value="hij" />
            <task name="task4" operation="or" value="klm" />
            <task name="task5" operation="or" value="nop" />
            <task name="task6" value="uvw" />
        </condition>
    </node3>
    <node3>
        <id>XYZ-987</id>
        <condition>
            <task name="task1" operation="and" value="abc" />
            <task name="task2" operation="and" value="efg" />
            <task name="task5" operation="or" value="nop" />
        </condition>
    </node3>
    <node3>
        <id>RST-567</id>
        <condition>
            <task name="task1" operation="and" value="abc" />
            <task name="task2" operation="and" value="efg" />
            <task name="task8" operation="and" value="jkl" />
            <task name="task9" operation="and" value="rst" />
            <task name="task10" value="xyz" />
        </condition>
    </node3>
    <node3>
        <id>PQR-345</id>
        <condition>
            <task name="task1" operation="and" value="ijk" />
            <task name="task2" operation="and" value="klm" />
            <task name="task8" operation="and" value="jkl" />
            <task name="task9" operation="and" value="rst" />
        </condition>
    </node3>
</node2>
</node1>

2 Answers 2

0

/node1/node2/node3[count(condition/task[not(@name='task1' and @value='abc') and not(@name='task2' and @value='efg') and @operation]) = count(condition/task[@operation='or'])]/id

will return all ids where:

  • the number of tasks that have an @operation attribute and aren't matched by the conditions @name='task1' and @value='abc' and @name='task2' and @value='efg'
  • equals the number of tasks where @operation = 'or'

which is ABC-123 and XYZ-987

Sign up to request clarification or add additional context in comments.

1 Comment

I had to use XPATH query twice and then find the intersection of the two results to get to my desired results. Above is small part of a large file, so there are more complex cases to get the correct output.
0

you have to re-structure your conditions:

/node1/node2/node3[(condition/task/@name='task1' and condition/task/@value='abc') and (condition/task/@name='task2' and condition/task/@value='efg')  and (condition/task/@name='task5' and condition/task/@value='nop')]/id

Parentheses () are optional in this case but they improve readability. note that as per the sample data you provided, LMN-543 also satisfies the query.

Returns

<id>ABC-123</id>
<id>LMN-543</id>
<id>XYZ-987</id>

I'm not very clear on your 'catch' condition, but based on what you say, it can be translated in each node having at most 2 operation="and" task. This makes and additional

and (count(condition/task[@operation='and']) < 3)

so the xpath becomes

/node1/node2/node3[(condition/task/@name='task1' and condition/task/@value='abc') and (condition/task/@name='task2' and condition/task/@value='efg')  and (condition/task/@name='task5' and condition/task/@value='nop') and (count(condition/task[@operation='and']) < 3)]/id

which returns:

<id>ABC-123</id>
<id>XYZ-987</id> 

2 Comments

Please see the question again. You have provided what I am already using. I need to get rid of LMN-543. Any solution for that?
edited answer to add additional constraint on operator

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.