1
<?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...

utij2004
  • 453
  • 1
  • 5
  • 14

2 Answers2

2

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!

grtjn
  • 20,254
  • 1
  • 24
  • 35
0

Something like this

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

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

Phil
  • 157,677
  • 23
  • 242
  • 245
  • Hi Phil, based on your expression I have tried (code in the question section) but it repeated the itemset, though if it is already in the list. Could you please help me again to solve that? – utij2004 Nov 19 '13 at 02:57
  • Your code doesn't look anything like my answer. You should be adding the search values as boolean **OR** conditions inside the `itemset` predicate – Phil Nov 19 '13 at 03:17
  • Actually I am new in XQuery. I am trying to find the way to do that. I want to search values dynamically and return the whole itemset based on it. Could you please write the FLWOR expression for that? – utij2004 Nov 19 '13 at 03:27