Модель данных XML опирается на понятие последовательности. Последовательность (sequence) - это упорядоченный набор нулевого или большего числа объектов. Объект (item) может быть узлом или атомарным значением. Атомарное значение (atomic value) - экземпляр одного из встроенных типов данных, определенных в XML Schema, таких как строки, целые и десятичные числа, даты. Узел (node) соответствует одному из семи видов: элементы, атрибуты, тексты, документы, комментарии, команды обработки и пространства имен. Узел может иметь другие узлы в качестве потомков, что позволяет образовывать одну или несколько иерархий узлов. Некоторые виды узлов, такие как элементы и атрибуты, имеют имена или типизированные значения, либо и то, и другое. Типизированное значение (typed value) - это последовательность из нуля или большего числа атомарных значений. Рассмотрим запросы XQuery на примере двух XML-документов «Аукцион» (Лист. 75), структуру см. Рис. 33 и Рис. 34.
Рис. 33. Модель данных из файла items.xml
Рис. 34. Модель данных из файла bids.xml
Лист. 75. XML-документы
Items.xml
<items>
<item status = “pending”>
<itemno>100</itemno>
<seller>Рога и Копыта</seller>
<description>Суповой набор</description>
<itemno>100</itemno>
<end-date>31.04.09</end-date>
</item>
<item status = “pending”>
...
</item>
</items>
Bids.xml
<bids>
<bid>
<itemno>100</itemno>
<bidder>Мария Ивановна</bidder>
<bid-amount>100</ bid-amount >
<bid-date>31.04.09</bid-date>
</bid>
<bid>
...
</bid>
</bids>
Выражения путив XQuery базируются на синтаксисе XPath. Выражение пути состоит из серии шагов, разделенных символом слэша (/). Результат каждого шага - последовательность узлов. Значение выражения пути - последовательность узлов, которая формируется на последнем шаге. Каждый шаг вычисляется в контексте некоторого узла, называемого контекстным узлом (context node). В общем случае шаг может быть любым выражением, возвращающим последовательность узлов. Один из важных видов шага, называемый осевым шагом (axis step), можно считать перемещением от контекстного узла по иерархии узлов в некотором направлении, называемом осью (axis). При перемещении по указанной оси осевой шаг выбирает узлы, которые удовлетворяют критерию выбора. Критерий выбора может выбирать узлы на основе их имен, положения по отношению к контекстному узлу или предикату, базирующемуся на значении узла. В XPath определяются 13 осей, и часть из них или все будут поддерживаться и в XQuery. Пока XQuery поддерживает шесть осей: child (узел-ребенок, то есть узел, вложенный в контекстный узел), descendant (потомок, то есть узел-ребенок, или ребенок ребенка и т.д.), parent (узел-родитель, то есть узел – контейнер для контекстного узла), attribute (атрибут узла), self (сам контекстный узел) и descendant-or-self (потомок или сам контекстный узел). Выражения пути могут быть записаны в полном или в сокращенном синтаксисе. Полный синтаксис для осевого шага предусматривает указание оси и критерия выбора, разделенных парой двоеточий. Пример запроса: перечислить описания всех товаров, предлагаемых к продаже Смитом – приведен на Лист. 76, сокращенного - Лист. 77.
Лист. 76. Пример полного путевого выражения XQuery
Разделение двух шагов двойным, а не одинарным слэшем означает, что второй шаг может выполнять поиск в нескольких уровнях иерархии, используя для этого ось descendants, а не одноуровневую ось child, например, Перечислить все элементы описания товаров, имеющиеся в документе items.xml (см. Лист. 78).
Лист. 78. Путевое выражение по оси «потомок»
document()//description
В выражении пути одинарная точка (.) указывает на контекстный узел, а две последовательные точки (..) - на предка контекстного узла. Эти нотации представляют собой сокращенное указание осей self и axes соответственно. Имена, присутствующие в выражениях пути, как правило, интерпретируются как имена узлов-элементов, однако если имя имеет префикс @, оно интерпретируется как имя узла-атрибута. Это сокращение для шага, который выполняет поиск вдоль оси attribute, например, найти атрибут статуса для товара, который является предком данного описания товара (см. Лист. 79).
Лист. 79. Путевое выражение по оси «атрибут»
$description/../@status
Форма записи для селекции (предиката) – квадратные скобки:
Item [reserve-price > 1000] – запись условия
item [5] – выбор пятого узла
item [reserve-price] - выбираются узлы item, у которых имеется узел-потомок reserve-price, вне зависимости от его значения.
Выражения пути - мощное средство, но им свойственно существенное ограничение: они способны выбирать только существующие узлы. В полном языке запросов необходимо наличие средства конструирования новых элементов и атрибутов, а также возможность указания их информационного наполнения и взаимосвязей. Это обеспечивается в XQuery с помощью вида выражения, называемого конструктором элементов (element constructor) – см. Лист. 80.
Лист. 80. Конструктор элемента
<highbid status = "pending">
<itemno>4871</itemno>
<bid-amount>250.00</bid-amount>
</highbid>
Вычисления заключаются в фигурные скобки (см. Лист. 81)
В приведенных примерах конструкторов элементов, хотя содержимое элементов может быть вычисляемым, имя конструируемого элемента - известная константа. Однако иногда необходимо сконструировать элемент, имя которого, как и его содержимое, вычисляется. Для этого в XQuery определяется специальный вид конструктора, называемого вычисляемым конструктором элемента (computed element constructor). Он состоит из ключевого слова element, за которым следуют два выражения в фигурных скобках - первое вычисляет имя элемента, а второе - его содержимое (см. Лист. 82 и Лист. 83).
Лист. 82. Вычисляемый конструктор элемента
element{name($e)}{$e/@*, data($e)*2}
Лист. 83. Конструктор атрибута
attribute{if $p/sex = "M" then "father" else "mother"}{$p/name}
Конструкция FLWR(for, let, where, return) обеспечивает дополнительные способы связывания переменных. В for перечисляются объекты, для которых выполняются дальнейшие действия, как правило, эти объекты описываются запросом. В let делаются вычисления, в where прописываются условия. В return описывается то, что надо возвратить, как правило, это конструктор элемента. Например, для каждого товара, который имеет более десяти ставок, создать элемент popular-item, содержащий номер товара, описание и число ставок.
Лист. 84. Конструкция FLWR
for $i in
document("items.xml")/*/item
let $b := document("bids.xml")
/*/ bid[itemno = $i/itemno]
where count ($b) > 10
return
<popular-item>
{
$i/itemno,
$i/description,
<bid-count> {count
($b)}</bid-count>
}
</popular-item>
В XQuery обеспечиваются обычные арифметические операции: +, - , *,div и mod, а также агрегатные функции sum,avg,count,max и min, которые применяются к последовательности чисел и возвращают числовой результат, операции над последовательностями: union, intersect, exept, условные выражения: if then else, кванторные выраженияevery и some. Например, найти товары в items.xml, для которых все полученные ставки более чем вдвое превысили начальную цену. Получить копии всех таких элементов item, и поместить их в новый элемент с именем underpriced-items (см. Лист. 85).
Лист. 85. Кванторы в XQuery
<underpriced items>
for $i in document("items.xml")
where every $b in document("bids.xml")
/*/bid [itemno = $i/itemno]
satisfies $b/bid-amount
> 2 * $i/reserve-price
return $i
</underpriced-items>
Есть в Xquery и функции (см. Лист. 86)
Лист. 86. Функции
define function highbid(element $item)
returns decimal
{
max(document("bids.xml")
//bid [itemno = $item/itemno]/bid-amount)
}
highbid(document("items.xml")
//item [itemno = "1234"])
Подробнее о XQuery см. [8].
Д/З 13. Пример из Д/З 11 и Д/З 12 представьте в виде страничек XML, приведите пример конструкции FLWR с вычисляемым конструктором, условиями и путевыми выражениями разного вида (по оси «потомок» или «ребенок» и «атрибут»).