Ограничения XML и совместимость с SQL/XML#
Примечание
Эта страница переведена при помощи нейросети GigaChat.
Значительные изменения спецификаций, связанных с XML, были внесены в ISO/IEC 9075-14 (SQL/XML) с выходом стандарта SQL:2006. Реализация PostgreSQL типа данных XML и соответствующих функций в основном следует более раннему изданию от 2003 года, заимствуя некоторые элементы из последующих изданий. В частности:
Вместо того чтобы предоставлять семейство типов данных XML для хранения «документов» или «содержимого», типизированных либо нетипизированных по схеме XML-схемы, а также отдельного типа
XML(SEQUENCE)для произвольного содержимого XML, PostgreSQL предоставляет единый типxml, который может хранить «документы» или «содержимое». Эквивалента стандартного типа «последовательность» здесь нет.PostgreSQL реализует две функции, введенные в стандарте SQL:2006, но использует их варианты, основанные на языке XPath 1.0 вместо языка запросов к XML, указанного в стандарте.
PostgreSQL не поддерживает предложения
RETURNING CONTENTиRETURNING SEQUENCE, функции, определенные со ссылками на них в спецификации, возвращают содержимое неявно.
Этот раздел описывает некоторые различия, с которыми можно столкнуться.
Запросы ограничиваются языком XPath версии 1.0#
Функции PostgreSQL, специфичные для работы с типом данных XML, xpath() и xpath_exists(), используют язык XPath для выполнения запросов к документам XML. Кроме того, PostgreSQL предлагает только те варианты стандартных функций XMLEXISTS и XMLTABLE, которые официально должны использовать язык XQuery, но фактически работают исключительно с XPath. Для всех этих функций PostgreSQL полагается на библиотеку libxml2, которая поддерживает только версию XPath 1.0.
Между языками XQuery и версиями XPath начиная с 2.0 существует тесная связь: любое выражение, синтаксически корректное и успешно выполняемое в обоих языках, дает одинаковый результат (за исключением незначительных случаев выражений, содержащих числовые ссылки на символы или предопределенные сущности, которые заменяются соответствующим символом в XQuery, тогда как в XPath они остаются неизменными). Однако такой связи между этими языками и версией XPath 1.0 нет; это был более ранний язык, отличающийся во многих аспектах.
Следует учитывать два вида ограничений: ограничение перехода от XQuery к XPath для функций, указанных в стандарте SQL, и ограничение использования XPath до версии 1.0 как для стандартных функций, так и для функций, специфичных для PostgreSQL.
Переход от XQuery к XPath#
По сравнению с XPath возможности языка XQuery включают следующие особенности:
Выражения XQuery могут создавать и возвращать новые узлы XML помимо любых возможных значений XPath. XPath может генерировать и возвращать значения атомарных типов (числа, строки и др.), но он способен вернуть лишь те узлы XML, которые уже присутствовали в документах, предоставленных на вход выражения.
XQuery имеет управляющие конструкции для итерации, сортировки и группировки.
XQuery позволяет объявлять и использовать локальные функции.
Последние версии XPath начинают предлагать аналогичные возможности (например, функциональные стили for-each и sort, анонимные функции и parse-xml для создания узла из строки), однако таких возможностей не было до выхода XPath 3.0.
Использование XPath версии 1.0#
Разработчики, знакомые с XQuery и версиями XPath 2.0 и выше, столкнутся с рядом различий при работе с XPath 1.0:
Базовый тип выражения XQuery/XPath –
sequence, который может содержать узлы XML, атомарные значения или оба варианта сразу, отсутствует в XPath 1.0. Выражение версии 1.0 способно выдавать только набор узлов (содержащий ноль или больше узлов XML) или единственное атомарное значение.В отличие от последовательности XQuery/XPath, которая может содержать любые желаемые элементы в любом порядке, набор узлов XPath 1.0 не гарантирует определенного порядка элементов и, подобно любому множеству, не допускает повторяющихся экземпляров одного элемента.
Примечание
Библиотека libxml2 всегда возвращает наборы узлов в том же относительном порядке, в котором они находились в исходном документе, хотя документация библиотеки не гарантирует такого поведения, и выражение XPath 1.0 не может его контролировать.
Хотя XQuery/XPath предоставляют все типы, определенные в XML-схеме, множество операторов и функций над ними, XPath 1.0 располагает только наборами узлов и тремя атомарными типами
boolean,doubleиstring.У XPath 1.0 нет условного оператора. Например, выражение XQuery/XPath вроде
if ( hat ) then hat/@size else "no hat"не имеет эквивалента в XPath 1.0.Сравнение строковых значений в XPath 1.0 невозможно напрямую. Оба выражения
"cat" < "dog"и"cat" > "dog"ложны, поскольку представляют собой числовое сравнение двух объектовNaN. Напротив, выражения=и!=сравнивают строки именно как строки.XPath 1.0 размывает разницу между сравнениями значений (сравнения значений) и общими сравнениями (общие сравнения), определяемые в XQuery/XPath. И
sale/@hatsize = 7, иsale/@customer = "alice"являются экзистенциальными сравнениями, истинными, если имеется любой узелsaleс заданным значением атрибута, тогда какsale/@taxable = false()представляет собой сравнение значений с эффективным булевым значением целого набора узлов. Оно будет истинным только в случае отсутствия у любого узлаsaleатрибутаtaxableвообще.В модели данных XQuery/XPath узел документа может иметь форму документа (то есть ровно один верхний элемент с комментариями и инструкциями обработки вне него) или форму содержимого (без соблюдения этих ограничений). Его аналог в XPath 1.0, корневой узел, может существовать только в форме документа. Это одна из причин, почему значение
xml, передаваемое в качестве контекстного элемента любой основанной на XPath функции PostgreSQL, обязательно должно находиться в форме документа.
Перечисленные здесь различия далеко не исчерпывают список. В XQuery и версиях XPath 2.0 и выше предусмотрен режим совместимости с XPath 1.0, и списки изменений библиотеки функций и самого языка, применяемые в этом режиме, составленные консорциумом W3C, дают более полное представление о различиях (хотя оно тоже неполное). Режим совместимости не делает последующие языки полностью эквивалентными XPath 1.0.
Соответствие между типами и значениями данных SQL и XML#
В стандарте SQL:2006 и более поздних версиях обе стороны преобразования между стандартными типами данных SQL и типами схем XML специфицированы четко. Однако правила выражаются с использованием типов и семантики языка XQuery/XPath и напрямую неприменимы к другой модели данных XPath 1.0.
Когда PostgreSQL отображает значения данных SQL в XML (например, в xmlelement), или из XML в SQL (например, в выходных столбцах xmltable), за исключением нескольких специально обработанных случаев, PostgreSQL просто предполагает, что строковая форма типа данных XML по XPath 1.0 будет действительна в качестве текстовой формы ввода для соответствующего типа данных SQL, и наоборот. Это правило обладает достоинством простоты при получении результатов, аналогичных тем, которые указаны в стандарте, для многих типов данных.
Если важна совместимость с другими системами, для некоторых типов данных может потребоваться явно использовать функции форматирования типов данных, чтобы получить стандартные сопоставления.
Случайные ограничения реализации#
Этот раздел касается ограничений, которые не присущи библиотеке libxml2, но применимы к текущей реализации в PostgreSQL.
Поддерживается только механизм передачи BY VALUE#
Стандарт SQL определяет два механизма передачи передач, которые применяются при передаче аргумента XML от SQL к XML-функции или приеме результата: BY REF, при котором конкретное значение XML сохраняет свою идентичность узла, и BY VALUE, при котором передается содержимое XML, но идентичность узла не сохраняется. Механизм можно указать перед списком параметров в качестве механизма по умолчанию для всех них или после любого параметра для переопределения по умолчанию.
Чтобы проиллюстрировать разницу, если x является значением XML, следующие два запроса в среде SQL:2006 дадут результаты true и false, соответственно:
SELECT XMLQUERY('$a is $b' PASSING BY REF x AS a, x AS b NULL ON EMPTY);
SELECT XMLQUERY('$a is $b' PASSING BY VALUE x AS a, x AS b NULL ON EMPTY);
PostgreSQL примет BY VALUE или BY REF в конструкции XMLEXISTS или XMLTABLE, но игнорирует их. Тип данных xml хранит сериализованное представление в виде символьной строки, поэтому нет никакой идентичности узлов, которую нужно было бы сохранить, а передача всегда фактически осуществляется посредством BY VALUE.
Невозможно передать именованные параметры запросам#
XPath-базированные функции поддерживают передачу одного параметра для использования его в качестве контекстного элемента выражения XPath, но не поддерживают передачу дополнительных значений, доступных выражению в виде именованных параметров.
Нет типа XML(SEQUENCE)#
Тип данных PostgreSQL xml может хранить значение только в форме DOCUMENT или CONTENT. Контекстный элемент выражения XQuery/XPath должен быть единственным узлом XML или атомарным значением, однако XPath 1.0 дополнительно ограничивает его до единственного узла XML и не имеет типа узла, допускающего CONTENT. В результате хорошо сформированное DOCUMENT – это единственная форма значения XML, которое PostgreSQL может предоставить в качестве контекстного элемента XPath.