2016-03-26 5 views
1

Я использую BaseX, который реализует XQuery 3.0.Embellish XML datasource в XQuery

Как мне украсить XML-источник данных в XQuery, не вводя все элементы, которые я хочу включить? Например, рассмотрим следующий XML:

<X> 
    <name>The root</name> 
    <Y> 
    <name> Level 1</name> 
    <Z> 
     <name>Level 2a</name> 
     <value>1</value> 
    </Z> 
    </Y> 
    <Y> 
    <name>Level 1b</name> 
    <Z> 
     <name>Level 2b</name> 
     <value>2</value> 
    </Z> 
    </Y> 
</X> 

Я хочу, чтобы добавить сумму всех значений на каждом уровне, как это:

<X> 
    <name>The root</name> 
    <value>3</value> 
    <Y> 
    <name> Level 1</name> 
    <value>1</value> 
    <Z> 
     <name>Level 2a</name> 
     <value>1</value> 
    </Z> 
    </Y> 
    <Y> 
    <name>Level 1b</name> 
    <value>2</value> 
    <Z> 
     <name>Level 2b</name> 
     <value>2</value> 
    </Z> 
    </Y> 
</X> 

Я могу использовать XQuery, как это для этого:

for $x in /X 
return 
<X>{ 
    $x/name, 
    <value>{sum($x//value)}</value>, 
    for $y in $x/Y 
    return 
    <Y>{ 
    $y/name, 
    <value>{sum($y//value)}</value>, 
    $y/Z 
    }</Y> 
}</X> 

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

ответ

2

Уверен, что вы можете! XQuery достаточно мощный. Еще лучше, BaseX не только поддерживает XQuery 3.0, но и XQuery Update, что, я думаю, здесь еще более уместно.

XQuery сам по себе является языком запросов. Поэтому, если вы хотите вставлять элементы в определенные места, вам всегда нужно воссоздать весь элемент, как в вашем примере. Тем не менее, XQuery Update добавляет конструкции для фактического обновления документов, например. вы можете использовать это для обновления значений в базе данных. Если вы просто хотите локально преобразовать значение, то есть transform expression.

Поскольку конструкция для этого в спецификации довольно громоздка, мы ввели ключевое слово BaseX update, которое вы можете использовать для преобразования XML-документа.

Таким образом, используя этот запрос может выглядеть следующим образом:

./X update (
    insert node <value>{sum(.//value)}</value> after ./name, 
    for $y in ./Y 
    return insert node <value>{sum($y//value)}</value> after $y/name 
) 

Конечно, в зависимости от того, как элементы повторяют (это совершенно ясно из Вашего вопроса), вы можете теперь использовать это, например, рекурсивно вставлять такой узел в соответствующие места. Еще один намек на это: если вы хотите динамически выбирать элемент, иногда нужно писать вместо /X лучше /*[local-name() = 'X'], так как теперь имя элемента не обязательно должно быть статическим.

+2

Awesome, я начинаю любить эту XQUERY вещь :) – wvdz

+0

ли вы имеете в виду с добавлением их рекурсивно, что я могу писать ' {сумму ($ что-то // значение)}' раз и использовать его рекурсивно? Не могли бы вы добавить пример того, как это сделать для данных примера, если это то, что вы имели в виду? Для моей ситуации я должен добавить агрегаты для примерно 15 значений для нескольких уровней, поэтому было бы здорово, если бы я мог сделать это таким образом, что мне нужно только один раз написать совокупный код. – wvdz