Ограничения 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 не гарантирует определенного порядка элементов и, подобно любому множеству, не допускает повторяющихся экземпляров одного элемента.
(ru-ru.xml-limits-conformance.примечание)=
ПримечаниеБиблиотека 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.