XML - статьи

/A> Расширение XPath переходами по дугам языка XLink


Заметим, что термин ось (axis) в XPath очень близок термину переход (traverse) в XLink, поскольку и тот, и другой подразумевают перемещение с одного места в документе на другое. Данное наблюдение убеждает нас в том, что при построении на основе XPath языка запросов к совокупности связанных XML-документов операции перехода по дуге XLink в языке XPath должна соответствовать ось. По аналогии с англоязычным названием для перехода в XLink назовем эту ось "traverse''.

На содержательном уровне, если имеются узлы A и B, такие, что для некоторой дуги XLink узел A является исходным ресурсом, а узел B - целевым, то при применении оси traverse к узлу A как к контекстному узлу результатом будет узел B.

Если следовать общему стилю, принятому в Спецификации XPath при определении осей, то более строгое определение оси traverse будет выглядеть так:

Определение 1.   Ось traverse содержит все узлы, являющиеся целевыми ресурсами для всех дуг XLink, для которых контекстный узел служит исходным ресурсом.

Из определения следует, что ось traverse возвращает непустой набор узлов только тогда, когда контекстный узел является исходным ресурсом хотя бы для одной дуги языка XLink.

Необходимо отметить, что осью traverse могут быть выбраны узлы, находящиеся в другом XML-документе, нежели контекстный узел; т.к. дуги языка XLink могут соединять ресурсы, находящиеся в разных XML-документах. Также в результате применения к контекстному узлу оси traverse может быть получен набор узлов из нескольких разных XML-документов, поскольку контекстный узел может быть исходным ресурсом для нескольких дуг XLink, и целевые ресурсы этих дуг могут располагаться в нескольких разных XML-документах.

Если целевой ресурс является удаленным ресурсом в терминах XLink и представляет собой целиком XML-документ (т.е. при адресации к данному ресурсу не используется идентификатор фрагмента на языке XPointer), то осью traverse будет выбран элемент документа. Если при адресации к удаленному целевому ресурсу Унифицированный Идентификатор Ресурса (URI) используется совместно с идентификатором фрагмента на языке XPointer и данный идентификатор фрагмента вычисляется в некоторый набор узлов, то осью traverse будет выбран весь этот набор узлов.

Выражение на языке XPath, расширенном предлагаемой осью traverse, позволяет прикладному приложению оперировать не с одним деревом XML-документа, а уже с деревьями нескольких документов, соединенных между собой с помощью ссылок языка XLink. При этом оси, определяемые Спецификацией XPath, замкнуты внутри отдельного дерева документа, а ось traverse позволяет осуществить переход между деревьями.

Необходимо отметить, что хотя совокупность XML-документов, соединенных ссылками XLink, представляет собой граф, вычисление любого выражения XPath, расширенного предлагаемой осью traverse, всегда будет конечным по времени. Данное свойство предлагаемого расширения языка XPath объясняется тем, что все оси, являющиеся транзитивным замыканием других осей, не могут зациклиться, поскольку замкнуты внутри конкретного дерева XML-документа, где циклы отсутствуют по определению дерева. Вычисление оси traverse также всегда конечно, поскольку для любого набора узлов существует лишь конечное число дуг XLink, исходными ресурсами которых являются узлы из данного набора.

Предложенная ось органичным образом вписывается в язык XPath, и при использовании данной оси в шаге доступа XPath полностью сохраняется семантика остальных составляющих шага доступа - теста узла и предикатов. Ввиду того, что по оси traverse можно перейти на узлы произвольного типа, тест узла помогает конкретизировать тип и, возможно, имя узлов, выбираемых шагом доступа.

Предикаты могут быть использованы для дальнейшего просеивания получаемого набора узлов в соответствии с некоторыми более сложными условиями. Как и для других осей, определенных спецификацией XPath, при применении предикатов к результату оси traverse контекстный размер равен количеству узлов в наборе, подлежащему фильтрации. Что касается контекстной позиции каждого узла, то для неупорядоченных наборов узлов - таких как атрибуты и объявления пространств имен - в Спецификации XPath сопоставление каждого узла с контекстной позицией объявляется зависящим от реализации [6]. Аналогичный подход может быть применен и для набора узлов, получаемый в результате оси traverse, т.к. по этой оси в общем случае осуществляется переход сразу по нескольким дугам XLink, которые не упорядочены между собой. Альтернативным подходом к сопоставлению узла с контекстной позицией может быть подход, принятый в языке XQuery: узлы в пределах одного XML-документа упорядочиваются в порядке обхода дерева документа, узлы из разных документов упорядочиваются произвольным, но единообразным образом для конкретной реализации [5].

Предлагаемая дополнительная ось traverse позволяет прикладному приложению осуществлять переходы по дугам языка XLink полностью прозрачным образом, без необходимости распознавать элементы XLink в XML-документе и разбирать их в соответствии с синтаксисом языка XLink с целью извлечения семантики дуг. Вне зависимости от того, где была определена дуга - в простой ссылке, или в расширенной ссылке, располагающейся в том же документе, или даже в отдельном документе, - переход по дуге осуществляется унифицированным образом.

Для иллюстрации предлагаемого расширения языка XPath осью traverse вернемся к рисунку 1, выражающему систему заказа товаров в виде 3 связанных XML-документов, и рассмотрим несколько примеров написания практических запросов к данной системе связанных документов.

Пример 1.   Найдем имена всех клиентов, заказавших принтеры.


Для получения ответа на этот запрос требуется соединить данные изо всех 3 XML-документов на рис. 1, и соединение должно проводиться на основе ссылок XLink, связывающих части этих документов. Поскольку в рассматриваемой системе связанных XML-документов все ссылки языка XLink исходят из документа "purchase-orders.xml", описывающего сделанные заказы, то запрос будет адресоваться именно к этому документу, и наличие ссылок XLink позволит выбрать необходимую информацию из остальных документов с помощью оси traverse. Путь доступа, реализующий требуемый запрос, может быть записан следующим образом: //order[entry/item/traverse::printer]/

   customer/traverse::person/name/text()

Шаг доступа, содержащий предикат и записанный в первой строке пути доступа, выбирает те выполненные заказы, в которых имеется хотя бы одно вхождение (entry) принтера среди заказанных товаров. Ось traverse внутри предиката осуществляет переход из каждого вхождения в заказе на каталог товаров; и тест узла printer позволяет указать, что из всех заказанных элементов каталога нас интересуют принтеры.

Во второй строке пути доступа, после того, как заказы были выбраны, осуществляется адресация к именам клиентов, сделавших соответствующие заказы. При адресации к именам клиентов снова используется ось traverse, и в этом случае она осуществляет переход уже на конкретного человека в документе "clients.xml", т.к. переход осуществляется по ссылке, ведущей от заказа к покупателю.

Результат вычисления запроса выбирает имя искомого клиента: John Smith

Пример 2.  Найдем список товаров, заказанных важным клиентом (в описании которого имеется вложенный элемент <VIP/>).

С помощью языка XPath, расширенного осью traverse, данный запрос может быть реализован в виде следующего пути доступа: //order[customer/traverse::person/VIP]/

   entry/item/traverse::*

В отличие от примера 1, здесь заказы фильтруются в соответствии с условием, накладываемым уже на клиента.

Результат запроса состоит из двух элементов каталога, и в соответствии с нотацией, принятой в XQuery для записи последовательности из нескольких узлов [5], мы записываем результат в круглых скобках, отделяя узлы друг от друга при помощи запятых: ( <printer>

    <lot>001</lot>

    <descr>Ink jet</descr>

    <price>450</price>

  </printer>,

  <display>

    <lot>003</lot>

    <descr>Color, Digital</descr>

    <warranty>2 years</warranty>

    <price>500</price>

  </display> )


Содержание раздела