Как ограничить порядок возврата в результатах XQuery?

Это вопрос для новичков. Я только недавно начал изучать XQuery и XPath.

Рассмотрим этот XML

<employees>
    <employee empid="1">
        <ename>KING</ename>
        <mgr></mgr>
        <hiredate>17-11-1981</hiredate>
    </employee>
    <employee empid="2">
        <ename>BLAKE</ename>
        <mgr>7839</mgr>
        <hiredate>1-5-1981</hiredate>
        <test>
            <sub1>one</sub1>
            <sub2>two</sub2>
        </test>
    </employee>
</employees>

Когда я выполняю следующий XQuery,

let $db := db:open("example", "documents/employee.xml")
for $item in $db/(/employees/employee,/employees/employee/test)
let $empid := $item/@empid
let $ename := $item/ename
let $sub1 := $item/sub1
let $hiredate := $item/hiredate
let $sub2 := $item/sub2
return ($empid,$ename,$sub1,$hiredate,$sub2)

Я получил...

empid="1"
<ename>KING</ename>
<hiredate>17-11-1981</hiredate>
<sub1>empid1-one</sub1>
empid="2"
<ename>BLAKE</ename>
<hiredate>1-5-1981</hiredate>
<sub1>empid2-one</sub1>
<sub2>empid2-two</sub2>

Результат, который я надеюсь получить ...

empid="1"
<ename>KING</ename>
<sub1>empid1-one</sub1>
<hiredate>17-11-1981</hiredate>
empid="2"
<ename>BLAKE</ename>
<sub1>empid2-one</sub1>
<hiredate>1-5-1981</hiredate>
<sub2>empid2-two</sub2>

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

Может кто-нибудь указать мне правильное направление? Спасибо


person beyonddc    schedule 16.02.2016    source источник


Ответы (2)


har07 уже дал хороший ответ, примите этот ответ, а не мой. Как дополнение, узлы атрибутов не могут выводиться без родительского элемента. Вы можете изменить переменную атрибута следующим образом:

let $empid := $item/@empid/concat(name(), '=', ., '&#10;')

и если вам важны новые строки больше, чем строки, содержащие только пробелы:

let $empid := $item/@empid/concat('&#10;',name(), '=', ., '&#10;')

и на выходе будет

<?xml version="1.0" encoding="UTF-8"?>
empid=1
<ename>KING</ename>
<hiredate>17-11-1981</hiredate>
empid=2
<ename>BLAKE</ename>
<sub1>one</sub1>
<hiredate>1-5-1981</hiredate>
<sub2>two</sub2>

Фактически, вывод - это вообще не XML, и нет смысла иметь объявление XML. Использовать

declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:omit-xml-declaration "yes";

избавиться от объявления. Это должно работать с новейшей версией BaseX. Тогда вывод будет

empid=1
<ename>KING</ename>
<hiredate>17-11-1981</hiredate>
empid=2
<ename>BLAKE</ename>
<sub1>one</sub1>
<hiredate>1-5-1981</hiredate>
<sub2>two</sub2>
person Mathias Müller    schedule 16.02.2016

Фактически, XQuery не меняет порядок возвращаемых значений, который вы указали. То, что вы заметили, связано с тем, что ваш код сначала выполняет цикл по всем employee элементам, а затем по test элементам, говоря in $db/(/employees/employee,/employees/employee/test).

Предполагая, что у одного employee может быть только один test дочерний элемент, вы можете вместо этого попробовать следующий способ:

let $db := db:open("example", "documents/employee.xml")
for $item in $db/employees/employee
let $empid := $item/@empid
let $ename := $item/ename
let $sub1 := $item/test/sub1
let $hiredate := $item/hiredate
let $sub2 := $item/test/sub2
return ($empid,$ename,$sub1,$hiredate,$sub2)
person har07    schedule 16.02.2016
comment
Это не работает, потому что узлы атрибутов ни к чему не прикрепляются. Как насчет let $empid := $item/@empid/concat(name(), '=', ., '&#10;')? - person Mathias Müller; 16.02.2016