FLWOR-выражение
FLWR-выражение (for, let, where, return) стало FLWOR-выражением (где "O" обозначает "order by").
Каждый раздел order by может содержать несколько ключей сортировки, каждый из которых включает выражение и может включать указания, должна ли быть сортировка устойчивой, должна ли она производиться по возрастанию или же по убыванию, считается ли пустая последовательность большей или же меньшей любого айтема, и должна ли использоваться схема сортировки (collation sequence), отличная от схемы, применяемой по умолчанию.
Каждое выражение в разделе order by вычисляется для каждого связывания переменных в разделах for и let, которое не исключается разделом where. Если какое-либо выражение производит последовательность из более чем одного айтема, то возвращается ошибка. Все значения типа xdt:untypedAtomic приводятся к xs:string. Если для какого-либо ключа сортировки типы значений различаются (после подстановки подтипа и расширения типа), то возвращается ошибка. Следующий запрос возвращает данные о недавно нанятых служащих, упорядоченные сначала по длительности обучения, а затем по номерам отделов. for $e in doc('employees.xml')//employee where current-date() - $e/hireDate < xdt:dayTimeDuration('P60D') order by $e/HSYears + $e/CollegeYears descending, $e/dept empty greatest return $e
Выбор того, считается ли пустая последовательность большей или меньшей любого айтема, может быть сделан в прологе запроса. В реализации XQuery любой из этих вариантов может быть принят по умолчанию.
В FLWOR-выражении также появился раздел at, который связывает позицию айтема в последовательности одновременно со связыванием значения этого айтема.
Следующий запрос возвращает данные о десяти служащих, работающих в компании дольше всех других служащих: for $e at $p in (for $oe in //employee order by $oe/@hireDate descending return $oe) where $p <= 10 return $e
Граничные пробелы
У объявления boundary-space имеются значения preserve и strip. Оно определяет, будут ли сохраняться граничные пробелы конструктором элемента. Рассмотрим пример: declare boundary-space preserve; <test> <inner-element/> </test>
У возвращаемого элемента имеются три ребенка: текстовый узел, содержащий несколько пробелов, узел-элемент и еще один текстовый узел. При указании strip у результирующего узла-элемента был бы только один ребенок. Если это объявление не используется, по умолчанию принимается strip.
Конструирование
У объявления construction также имеются значения preserve и strip. В этом случае пользователь выбирает, должны ли сохраняться аннотации типов при конструировании новых узлов-элементов или узлов-документов. Если выбирается strip, то конструируемый элемент и все его дети аннотируются с использованием xdt:untyped, и все его узлы-атрибуты аннотируются с использованием xdt:untypedAtomic. Если выбирается preserve, то конструируемый элемент аннотируется с использованием xdt:anyType, а у всех его узлов-элементов и узлов-атрибутов сохраняются их существующие аннотации.
Модель данных XQuery 1.0 и XPath 2.0 (XDM)
В дополнение к типам, определенным в документе XML Schema Part 25, в XDM определяются еще пять типов. Два из них обсуждались в нашей предыдущей статье: xdt:dayTimeDuration и xdt:yearMonthDuration, где xdt является префиксом пространства имен http://www.w3.org/2005/xpath-datatypes.
Тип xdt:untyped назначается узлам-элементам, которые не валидированы или валидированы в режиме пропуска (skip mode). Этот тип также назначается конструируемым элементам, когда режимом конструирования является strip (обсуждается позже). Все дети элемента, аннотируемого как xdt:untyped, также аннотируются как xdt:untyped.
Тип xdt:untypedAtomic назначается значениям, которые являются атомарными, но у которых отсутствует более точный тип. Этот тип назначается атрибутам, валидированным в режиме пропуска.
Базовым типом типа xdt:anyAtomicType является xs:anySimpleType, и из xdt:anyAtomicType порождаются все примитивные атомарные типы. В их число входят xs:string, xs:float и xdt:untypedAtomic. По своей природе этот тип является абстрактным, поскольку этим типом не будет аннотировано ни одно значение. С точки зрения XQuery этот тип вносится в иерархию типов XML Schema.
Модули
Библиотечный модуль – это коллекция переменных и функций в целевом пространстве имен, которая может импортироваться в запрос. module namespace univ ="http://www.example.com/university";
declare function univ:gpa ($e as element (student)) as xs:decimal { for ... } ;
Эту функцию можно было бы вызвать в запросе следующим образом: import module namespace univ ="http://www.example.com/university"; declare variable $id external;
univ:gpa(//student[id=$id])
Объявления в прологе XQuery
В прологе XQuery теперь может содержаться большее число объявлений. Среди них объявление граничных пробелов (boundary-space declaration), объявление базового URI (base URI declaration), объявление конструирования (construction declaration), объявление копирования пространств имен (copy namespaces declaration) и объявление опций (option declaration). В этом разделе мы обсудим некоторые из этих объявлений.
Опции
Объявление option – это один из нескольких механизмов расширений, которые XQuery предоставляет реализаторам. В объявлении опций содержится квалифицированное имя QName и строка. Если QName распознается реализацией, оно может воздействовать на обработку запроса способом, выбранным в реализации. Если QName не распознается, то игнорируется. Таким образом, расширения, выбранные в одной реализации, не приводят к сбоям при выполнении на другой реализации.
Рассмотрим расширение, позволяющее пользователю устанавливать значение тайм-аута в секундах, после истечения которого обработка запроса прекращается, и возвращается ошибка. declare namespace myxquery='...'; declare option myxquery:timeout '10'; for $e in //employees ...
Предстоящая работа
Продолжая продвигать XQuery к его публикации в качестве рекомендации W3C, мы ведем разработку средств, которые будут добавлены к XQuery 1.0.
Опубликовано несколько рабочих проектов (Working Drafts, WD) XQuery 1.0 and Path 2.0 Full-Text7. Опубликованы требования к XQuery Update Facility8, но исходный WD еще не опубликован.
Мы ожидаем, что в начале следующего года Рабочая группа по XQuery начнет анализировать средства, которые нельзя было включить в XQuery 1.0, на предмет включения в следующую версию рекомендаций.
Пространства имен в области действия
Было решено не поддерживать в XQuery узлы-пространства имен и ось пространств имен, поддерживаемые в XPath 1.0. Вместо этого, в XQuery с узлами ассоциируются связывания пространств имен в области действия (in-scope namespace bindings).
В XQuery также имеется набор статически известных пространств имен, используемых при разрешении квалифицированных имен (QName). В число этих статически известных пространств имен входят fn, xml, xs, xsi, xdt и local. В реализации могут быть добавлены собственные связывания пространств имен, и пользователь может добавить связывания в прологе запроса: declare namespace myco="http://www.example.com/myco";
<myco:result> { for ... } </myco:result>
Пространства имен в области действия могут влиять на сериализацию узлов-элементов, а также на поведение небольшого числа функций. С узлом, конструируемым в приведенном примере, ассоциируется одно связывание пространства имен. Пространство имен для myco берется из пространств имен, статически известных во время конструирования узла.
При конструировании узла его связывания пространств имен включают одно связывание, используемое в имени элемента; связывания в именах атрибутов; связывания, используемые в атрибутах объявления пространства имен; и связывания в объявлениях атрибутов пространств имен окружающих конструкторов элементов, которые не подвергнуты перезаписи.
Рассмотрим следующий пример: import schema namespace hr="...";
validate strict { <hr:employee> <hr:skill xsi:type="xs:string"> unicycling </hr:skill> </hr:employee> }
Этот запрос приведет к ошибке, потому что связывание для xs не появится в валидируемом информационном наборе. В XQuery не уделяется особое внимание атрибуту xsi:type. Значение "xs:string" – это всего лишь нетипизированное значение атрибута, оно не выглядит как QName, и поэтому xs не добавляется к пространствам имен в области действия. Это означает, что оно не является частью информационного набора. Данный запрос можно исправить путем изменения стартового тега следующим образом: <hr:employee xmlns:xs ="http://www.w3.org/2001/XMLSchema"> . . . </hr:employee>
Более тонкое управление пространствами имен в области действия конструируемых элементов можно обеспечить с использованием объявления copy-namespaces в прологе запроса.
Сериализация
После публикации нашей предыдущей статьи рабочие группы создали новый документ: Сериализация XSLT 2.0 и XQuery 1.06. Материал этого документа был перемещен из спецификации XSLT 2.0, чтобы его можно было использовать и для XQuery 1.0. В этом документе определяются методы формирования выходных данных в форматах XML, XHTML, HTML и TEXT. В XQuery 1.0 используется только метод формирования выходных данных в формате XML, в то время как в XSLT используются все методы.
Для сериализации может предоставляться значение модели данных XQuery 1.0 и XPath 2.0 (XDM). Сначала выполняется нормализация последовательности (Sequence Normalization), затем – генерация разметки, расширение символов и кодирование.
Нормализация последовательности определяется в виде нескольких шагов, преобразующих экземпляр модели данных (data model instance) – последовательность значений и узлов – в единственный узел-документ. Атомарные значения приводятся к строкам и затем к текстовым узлам. Узлы-документы отбрасываются, но их дети сохраняются. Ошибкой сериализации является помещение в результирующий документ узла-атрибута, который не является ребенком некоторого узла-элемента.
В сериализации определяется ряд параметров, которые влияют на производимый результат. Например, значением omit-xml-declaration может yes быть или no. В каждом отдельном методе формирования выходных данных используются не все параметры.
Метод вывода в формате XML генерирует правильно построенную сущность XML-документа (well-formed XML document entity), если результат нормализации последовательности – это узел-документ с единственным ребенком, являющимся узлом-элементом, и без детей, которые представляют собой текстовые узлы. В противном случае генерируется правильно построенная, внешняя, обобщенная, анализируемая XML-сущность (well-formed XML external general parsed entity). В спецификации не говорится, как следует формировать эти сущности. Требуется только, чтобы при синтаксическом разборе результата и при генерации экземпляра модели данных с использованием результирующего информационного набора (infoset) получался один и тот же экземпляр модели данных. Более точно, эти экземпляры могут различаться, например, порядком узлов.
В течение сериализации не предпринимаются какие-либо попытки сохранения аннотаций типов. Если результат валидируется на соответствие XML Schema, то создаются новые аннотации типов.
и, возвращающие атомарные значения
В XPath 1.0 результатом шага путевого выражения являлась последовательность узлов в порядке документа с удаленными дубликатами. В XQuery 1.0 и XPath 2.0 допускается, чтобы на завершающем шаге путевого выражения производилась последовательность атомарных значений. Запрос, возвращающий список названий городов и штатов для всех служащих в Калифорнии, можно написать как //employee[address/state='CA'] /address/concat(city, ', ', state)
вместо for $a in //employee[address/state="CA"] /address return concat($a/city, ', ', $a/state)
Соответствие с XQuery и XQueryX
И для XQuery, и для XQueryX имеются декларации о соответствии, определяющие минимальное соответствие (Minimal Conformance) и набор необязательных возможностей.
Минимальная согласованность является самым низким уровнем согласованности, который может провозглашаться для XQuery. Минимальная согласованность охватывает все функциональные возможности XQuery за исключением следующих необязательных средств:
Средство импорта схемы (Schema Import Feature) – позволяет использовать import schema в прологе для обеспечения осведомленности XQuery об объявлениях элементов, атрибутов и типов. Средство валидации по схеме (Schema Validation Feature) – позволяет использовать выражение validate. Средство статической типизации (Static Typing Feature) – требует, чтобы XQuery обнаруживал и диагностировал ошибки типов на фазе статического анализа. При обработке некоторых запросов, которые могут успешно выполняться без статической типизации, будут возвращаться ошибки во время статического анализа. Наличие полных осей (Full Axis Feature) – позволяет использовать «обратные оси» ancestor, ancestor-or-self, following, following-sibling, preceding и preceding-sibling. Поддержка модулей (Module Feature) – позволяет использовать import module в прологе, и позволяет создавать библиотечные модули. Средство сериализации (Serialization Feature) – требует, чтобы реализация обеспечивала XML-сериализацию результата запроса. Средство тривиального встраивания XML – позволяет предоставлять запрос в виде XML-элемента:
<xqx:xquery>for $e in ... </xqx:xquery>.
Состояние XQuery
В ноябре 2005 г. кандидатами на рекомендацию (Candidate Recommendations, CR) стали следующие документы:
XQuery 1.0: An XML Query Language XML Path Language (XPath) 2.0 XSL Transformations (XSLT) Version 2.0 XQuery 1.0 and XPath 2.0 Data Model (XDM) XQuery 1.0 and XPath 2.0 Functions and Operators XQuery 1.0 and XPath 2.0 Formal Semantics XSLT 2.0 and XQuery 1.0 Serialization XML Syntax for XQuery 1.0 (XQueryX)
Над большинством этих документов рабочая группа по XML Query работает в тесном контакте с рабочей группой по XSL. Большинство документов было подвергнуто двойному рецензированию Last Call Working Draft (WD), а несколько из них прошло тройное рецензирование. На последней стадии рецензирования рабочие группы отреагировали почти на 600 комментариев.
Назначение CR состоит в том, чтобы получить опыт реализации и обеспечить уверенность рабочей группы в том, что спецификация полна и однозначна. С этой целью рабочая группа по XML Query летом 2004 г. начала разработку тестового набора. Теперь XML Query Test Suite4 покрывает около 75% возможностей XQuery. Для завершения создания этого тестового набора и получения отчетов от реализаторов понадобится несколько месяцев. При наличии удачи и упорного труда со стороны ряда людей XQuery станет рекомендацией W3C до конца 2006 г.
Типы
После публикации нашей предыдущей статьи поменялись некоторые обозначения типов. Вместо того чтобы воспользоваться BNF, ограничимся рядом примеров:
xs:integer? | Последовательность из одного или более целых значений |
element()+ | Последовательность из одного или более элементов |
node()* | Последовательность из одного или более узлов |
item()+ | Один или несколько айтемов (узлов или атомарных значений) |
item()+ | Атрибут (одиночный) с любым именем и типом |
element (myco:address) |
Элемент с именем myco:address |
element (*, myco:addrType) |
Элемент с любым именем и типом myco:addrType |
schema-element(zip) | Элемент с именем zip (или в группе постановок с заголовком zip) с аннотацией типа, соответствующей типу элемента zip |
Обозначение типа можно использовать следующим образом: //employee [* instance of element (*, myco:addrType) ]
В ранних версиях XQuery допускались ссылки на элементы и атрибуты, локально объявленные в схеме, но эта возможность была исключена.
Входные данные для обработки XQuery
Сущности модели данных, с которыми может оперировать XQuery, могут предоставляться разными способами. В своей предыдущей статье мы описывали контекстный элемент (context item), обозначаемый через ".", и функции fn:doc и fn:collection. От упоминавшейся в той же статье функции xf:input отказались в пользу внешних переменных.
Введен вариант функции fn:collection без аргумента для ссылки на коллекцию по умолчанию, которая может предоставляться основной средой.
В реализации могут обеспечиваться переменные для использования в запросе. В запросе могут также определяться внешние переменные, значения которых должны поставляться основной средой. В объявлении переменной может содержаться ее тип. Если он не указывается, то основная среда обеспечивает тип переменной и ее значение.
Следующий запрос может исполняться с использованием переменной $custName, связанной с "Big Box". declare variable $custName as xs:string external;
fn:doc('orders.xml') /orders/order[@cust=$custName] ... <order id='444378' cust='Big Box'> ... </order>
это язык запросов, разработанный для
XQuery – это язык запросов, разработанный для формулировки запросов к реальным и виртуальным XML-документам и коллекциям этих документов. Разработка этого языка началась во второй половине 1999 г. В декабре 2002 г. мы представили ранний вариант XQuery1. Сейчас приближается публикация XQuery 1.0 в виде рекомендации W3C (W3C Recommendation), и мы хотели бы осведомить вас о развитии языка. Теперь мы можем говорить об этой области даже более авторитетно, чем в прошлый раз, потому что в октябре 2004 г. оба стали сопредседателями Рабочей группы W3C по XML Query (W3C XML Query Working Group)2.
Пол Коттон (Paul Cotton, Microsoft), который возглавлял группу с самого начала, в октябре отказался от этой роли. Его позиция в другом консорциуме не позволила ему остаться лидером группы XQuery 1.0 до момента его публикации в качестве рекомендации, хотя он определенно желал этого. Пол сыграл важную роль в процессе разработки XQuery, и его деятельность в качестве лидера группы заслуживает всяческих похвал.
В этой статье мы концентрируемся на изменениях, которые претерпел XQuery со времени нашей прежней публикации. Если вы незнакомы с XQuery, то вам, может быть, стоит взглянуть на нашу предыдущую статью до продолжения чтения данной статьи.
Выражение castable
Выражение castable возвращает булевское значение, показывающее, может ли выражение-аргумент быть успешно приведено к указанному типу. Без этого расширения у пользователя не было бы возможности предотвратить ошибку приведения типа, которая привела бы к ошибке выполнения всего запроса. (В будущей версии может появиться что-то подобное обработке исключительных ситуаций.)
Выражение extension
Выражение extension – это еще один механизм расширения, предоставляемый реализаторам XQuery. В то время как объявление extension воздействует на весь запрос, у выражения расширения имеется более ограниченная область действия. Для пояснения этой конструкции рассмотрим следующий пример. declare namespace xq1="..."; declare namespace xq2="...";
for $e in //employee[name='Jon Postel'] return (# xq1:prose English #) (# xq2:roman lower-case #) { $e/badge cast as xs:string }
Эти псевдокомментарии (pragma) "(# … #)", если они распознаются, могут изменять поведение приведения значений к строкам. Этот запрос может произвести "One Hundred Fifty Four", если в реализации распознается xq1:prose, "cliv", если распознается xq2:roman, и "154", если не распознается ни один из псевдокомментариев. Выражение в фигурных скобках "{}" может опускаться. Если оно опускается, и ни один из псевдокомментариев не распознается, генерируется ошибка.
Выражение validate
Выражение validate вызывает валидацию своего аргумента в соответствии с XML Schema. Сначала аргумент этого выражения преобразуется в информационный набор (infoset) с отбрасыванием всех аннотаций типов, которые содержатся в аргументе. Результатом валидации является новый элемент (с новым содержанием и с новой индивидуальностью) с аннотациями типов. Если не удается произвести успешную валидацию, то возникает динамическая ошибка.
С использованием выражения валидации аннотации типа могут быть применены к конструируемому элементу: validate { <myco:employee id='440612'> <name>Augustus Child</name> . . . </myco:employee> }
В этом случае в схеме myco должен содержаться глобально определенный элемент employee. У элемента name в конструируемом элементе имеется тип xdt:untyped, в то время как в валидированном результате у него имелся бы тип myco:nameType.
Выражения
К набору выражений XQuery добавлены castable, extension, ordered и unordered, а также немного изменен синтаксис cast, node comparison и validate.
тип выражения | синтаксис выражения |
cast | expr cast as type |
castable | expr castable as type |
validate | validate { expr } validate lax { expr } validate strict { expr } |
node comparison | is (от isnot отказались) |
extension | (см. ниже) |
ordered | ordered { expr } |
unordered | unordered { expr } |
Выражения ordered и unordered
Выражение ordered устанавливает режим упорядочивания для своего выражения-аргумента. Выражение unordered устанавливает режим неупорядочивания для своего выражения-аргумента.
Путевые выражения, включающие операцию "/" или "//", или шаг; выражения над множествами (union, intersect и except), а также FLWOR-выражения без раздела order by являются чувствительными к режиму упорядочивания. Если требуется упорядочивание, то каждое из этих выражений производит последовательность элементов в порядке документа. Если упорядочивание не требуется, то порядок элементов этой последовательности является произвольным. Ослабление порядка элементов может позволить оптимизатору выбрать более дешевую стратегию выполнения запроса.
Исходный режим упорядочивания может устанавливаться в прологе запроса. Если он не установлен, то по умолчанию требуется упорядочивание. Следующий запрос возвращает последовательность служащих в произвольном порядке, но во внутреннем путевом выражении используется упорядочивание для выбора служащих с должностью "VP" (вице-президент). declare ordering unordered; for $e in ordered { //employee[titles/title[last()] = 'VP'] } where $e[location/@state='NY'] return $e
XQuery 1.0 близок к завершению
Эндрю Эйзенберг (Andrew Eisenberg), Джим Мелтон (Jim Melton)
Перевод:
Оригинал: , SIGMOD Record, Vol. 34, No. 4, Dec. 2005
XQuery
XQuery 1.0 является почти строгим надмножеством XPath 2.0 – в XQuery 1.0 не используются узлы-пространства имен XPath и не поддерживаются оси пространства имен XPath.
XQueryX
XQueryX9 определяет XML-представление XQuery. В этой спецификации определяется структура элементов, отражающая абстрактный синтаксис XQuery. Определение XQueryX немного изменилось со времени нашей предыдущей статьи. В Примере 1 содержится простой XQuery-запрос и соответствующее XQueryX-представление.
Хотя XQueryX труднее читается и пишется людьми, у него имеется несколько полезных свойств. XQueryX-представления легко генерируются инструментальными средствами и многослойными приложениями, и они легко встраиваются в более крупные XML-документы, позволяя формулировать «запросы над запросами».
Конечно, все изменения, которым подвергся XQuery, в равной степени относятся и к XQueryX. Но в XQueryX имеется еще одно достаточно важное изменение. Во время нашей предыдущей публикации XML Schema, определяющая синтаксис XQueryX, основывалась на иерархии типов, которую оказалось трудно поддерживать при добавлении к языку новых возможностей, а также несколько затруднительно держать в голове человека. Эта иерархическая организация было заменена другой, основанной на группах подстановок XML Schema. Такой подход поддается более простому расширению при появлении новых языковых возможностей и более близок знатокам Schema. for $b in .//book return $b/title
<xqx:module xmlns:xqx="http://www.w3.org/2005/XQueryX" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xqx:mainModule> <xqx:queryBody> <xqx:flworExpr> <xqx:forClause> <xqx:forClauseItem> <xqx:typedVariableBinding> <xqx:varName>b</xqx:varName> </xqx:typedVariableBinding> <xqx:forExpr> <xqx:pathExpr> <xqx:argExpr> <xqx:contextItemExpr/> </xqx:argExpr> <xqx:stepExpr> <xqx:xpathAxis> descendant-or-self </xqx:xpathAxis> <xqx:anyKindTest/> </xqx:stepExpr> <xqx:stepExpr> <xqx:xpathAxis>child</xqx:xpathAxis> <xqx:nameTest>book</xqx:nameTest> </xqx:stepExpr> </xqx:pathExpr> </xqx:forExpr> </xqx:forClauseItem> </xqx:forClause> <xqx:returnClause> . . . </xqx:returnClause> </xqx:flworExpr> </xqx:queryBody> </xqx:mainModule> </xqx:module>
Пример 1. XQuery-запрос и его эквивалентное XQueryX-представление
Несколько небольших изменений было внесено также в схему XQueryX. Наиболее существенным изменением является новый элемент схемы <xqx:xquery>, используемый для тривиального встраивания текста XQuery (в читаемом человеком виде) в XML-документы.
Значения URI
В XQuery давно разрешено расширение типов (type promotion) числовых значений, от xs:decimal до xs:float и от xs:float до xs:double. После публикации нашей предыдущей статьи в XQuery было добавлено расширение от xs:anyURI до xs:string.
Без этого изменения запрос над бестиповым документом вида let $xq := 'http://www.w3.org/TR/xquery/' return count(//bib[ref=$xq])
вызвал бы ошибку типа для типизированного документа из-за сравнения xs:anyURI и значения xs:string. Его пришлось бы переписать к виду let $xq := 'http://www.w3.org/TR/xquery/' return count(//bib[ref=xs:anyURI($xq)])