Как получить родительский узел на основе значения дочернего узла с помощью XQuery

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

Предположим, у меня есть список отдельных элементов. Я хочу искать каждый элемент из набора элементов. Если в наборе есть этот элемент, я верну этот набор со всеми элементами. Например, у меня есть отдельный список предметов (молоко, бумага (это не фиксированный --- динамический список)). Молоко находится в наборе элементов-3 и наборе элементов-4, поэтому я добавлю набор элементов-3 и набор элементов-4 в новый список XML, тогда бумага будет только в наборе элементов 4. Но набор элементов-4 уже есть в списке, поэтому нет необходимости снова добавлять набор элементов 4. Мой вопрос заключается в том, как получить набор элементов с помощью XQuery на основе каждого элемента, и набор элементов добавляется только один раз в мой новый список. Я использую BaseX для запуска команды XQuery.

Ожидаемый результат выглядит следующим образом:

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

Код, который я пробовал:

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

Но он повторно возвращает набор элементов для двух или более различных элементов. Как остановить печать существующего набора элементов? Помогите пожалуйста мне...


person utij2004    schedule 19.11.2013    source источник


Ответы (2)


Ошибка в вашем коде заключается в том, что вы ищете каждое (отличное) значение отдельно. Как предложил Фил, вы должны выполнить комбинированный поиск всех значений в одном XPath. Если вы отбросите строку for и замените let $def выражением, которое ищет все значения, вы окажетесь там. Что-то вроде:

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

Здесь вы можете заменить $C любой последовательностью значений, например:

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

Оператор = способен сравнивать последовательности и наборы узлов, эффективно выполняя пересечение. Возвращает true, если пересечение не пусто.

ХТХ!

person grtjn    schedule 19.11.2013

Что-то вроде этого

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

Демо здесь — http://www.xpathtester.com/obj/01c525c6-14ae-427b-b6c6-26f8e1ef17a7

person Phil    schedule 19.11.2013
comment
Привет, Фил, основываясь на вашем выражении, я попытался (код в разделе вопросов), но он повторил набор элементов, хотя он уже есть в списке. Не могли бы вы помочь мне снова решить эту проблему? - person utij2004; 19.11.2013
comment
Ваш код не похож на мой ответ. Вы должны добавлять значения поиска как логические условия ИЛИ внутри предиката itemset - person Phil; 19.11.2013
comment
На самом деле я новичок в XQuery. Я пытаюсь найти способ сделать это. Я хочу динамически искать значения и возвращать весь набор элементов на его основе. Не могли бы вы написать выражение FLWOR для этого? - person utij2004; 19.11.2013