Оси
XQuery не имеет полного набора осей, используемых в выражениях пути XPath: это единственная часть XPath, которая не включена непосредственно в XQuery. XQuery не имеет осей following и preceding, following-sib-ling и preceding-sibling, а также оси ancestor. Почему было принято такое решение? Мне сложно объяснить этот факт, потому что я приводил доводы против такого решения, но аргументы обеих сторон были разумными, и я попробую воздать им должное.
Подход, используемый в XPath для выбора узлов в дереве, определяется способом, который некоторые называют навигационным. Я предпочитаю называть его функциональным, потому что слово навигационный подразумевает процедурные алгоритмы, но, по сути, означает то, что поиск узлов ведется на основании их взаимоотношений с другими узлами: три шага вверх, затем два влево, затем один шаг вниз. Такой подход традиционно является трудным для оптимизации. В базах данных, следующих реляционной традиции, подход состоит в выборе объектов на основании их свойств, а не описания маршрута, с помощью которого можно достичь этих объектов. Это заставляет некоторых людей, придерживающихся реляционной традиции, относиться с большим подозрением к выражениям пути и беспокоиться о сложности их оптимизации.
Некоторые разработчики реализаций XQuery также используют инструменты, существующие в базах данных, в которых структуры хранения и индексации хорошо настроены для реляционных данных и реляционных запросов. Адаптация этих инструментов к иерархическим структурам данных и рекурсивным выражениям пути – нелегкая задача, и запросы, которые хорошо вписываются в реляционный шаблон, вероятно, чаще будут выполняться в этом случае намного эффективнее, чем остальные запросы.
Любое выражение, включающее оси, отсутствующие в XQuery, может быть переписано таким образом, чтобы можно было избежать использования этих осей. Возьмем, например, запрос «Найти элемент figure, сразу за которым следует другой элемент figure без любого промежуточного текста или элемента». В XPath мы написали бы следующее: //figure[following-sibling::node()[1][self::figure]]
XQuery не имеет оси following-sibling, поэтому как же мы сможем выразить этот запрос? Одним из возможных способов будет такой: for $p in //* for $f at $i in $p/figure where $p/node()[$i+1][self::figure] return $f
Хотя данный способ кажется очень запутанным тем, кто знаком с XPath, мне сказали, что этот способ выглядит очень естественно для людей, думающих в терминах SQL. Является ли этот способ более легким для оптимизации, чем версия запроса XPath? Только не для процессора, оперирующего моделью дерева, выполненной в терминах полносвязной объектной модели либо в памяти, либо в постоянном хранилище (обычно в собственной базе данных XML, подобной ). Но для разработчиков, которые перевели дерево в структуру кортежей, представленную в табличном хранилище, – кто знает?
Возможно все сводится к различным представлениям относительно важности таких запросов. В документо-ориентированном XML важен порядок, и объекты вероятнее всего, будут идентифицированы по их взаимоотношению с другими объектами, а не по их свойствам. В информационно-ориентированном XML объекты, скорее всего, будут идентифицированы по их содержанию. Так что я сильно подозреваю, что реальной основной причиной принятия этого решения был естественный уклон к информационно-ориентированному XML, присутствующий в группе XQuery.