Question

<?xml version="1.0" encoding="utf-8"?>
<transaction>
    <itemset id="1">
        <item>pen</item>
        <item>notebook</item>
        <item>pencile box</item>
    </itemset>
<itemset id="2">
    <item>pen</item>
    <item>notebook</item>
    <item>pencile box</item>
    <item>ink</item>
</itemset>
<itemset id="3">
    <item>ink</item>
    <item>milk</item>
</itemset>
<itemset id="4">
    <item>pen</item>
    <item>notebook</item>
    <item>pencile box</item>
    <item>ink</item>
    <item>milk</item>
    <item>paper</item>
</itemset>
<itemset id="5">
    <item>pen</item>
    <item>ink</item>
    <item>notebook</item>
</itemset>
</transaction>

Suppose I have a list of distinct items. I want to search each item from an itemset. If the itemset have that item, then I will return that itemset with all items. For example, I have a distinct list of items (milk,paper (this is not fixed---dynamic list)). Milk is in itemset-3 and itemset-4, So I will add itemset-3 and itemset-4 in a new XML list, then paper is in itemset 4 only. But itemset-4 is already in the list so no need to add the itemset 4 again. My question is how do I get an itemset using XQuery based on each item and the itemset is added only once in my new list. I am using BaseX to run XQuery command.

Expected output looks like

    <?xml version="1.0" encoding="utf-8"?>
<transaction>
<itemset id="3">
    <item>ink</item>
    <item>milk</item>
</itemset>
<itemset id="4">
    <item>pen</item>
    <item>notebook</item>
    <item>pencile box</item>
    <item>ink</item>
    <item>milk</item>
    <item>paper</item>
</itemset>
</transaction>

The code I have tried:

let $src:= doc('XML/test_my.xml')/transaction
let $allitems := $src/itemset/item
let $C:=distinct-values($allitems)
for $value in $C
    let $def:=$src/itemset[item=$value]
    return $def

But it return itemset repeatedly for two or more distinct items. How do I stop to print the existing itemset? Please help me...

Was it helpful?

Solution

The mistake in your code is that you search for each (distinct) value separately. As suggested by Phil, you should do a combined search for all values in one XPath. If you drop the for line, and replace the let $def with an expression that searches all values, you'll be there. Something like:

let $allitems := $src/itemset/item
let $C:=distinct-values($allitems)
let $def:=$src/itemset[item=$C]
return $def

You can replace $C here by any sequence of values, for instance:

let $C := ('milk', 'paper')

The = operator is capable of comparing sequences and node-sets, effectively doing an intersect. It returns true if the intersect isn't empty.

HTH!

OTHER TIPS

Something like this

/transaction/itemset[item='milk' or item='paper']

Demo here - http://www.xpathtester.com/obj/01c525c6-14ae-427b-b6c6-26f8e1ef17a7

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top