Конструкторы узлов

Язык запросов для XML не был бы самим собой, если бы в нем нельзя было создавать узлы XML-документа. К сожалению, здесь довольно сложно провести аналогию с обычным SQL, потому что в нем вы не имеете возможности получать результирующую выборку в каком-либо виде, отличном от табличного.

Изменение результирующей выборки в XQuery производится при помощи конструкторов узлов. Эти конструкторы предназначены для создания узлов элементов, атрибутов, документов, инструкций обработки, комментариев, пространств имен и текстовых узлов. Кроме этого, есть возможность создавать секции CDATA. В SQL Server-е пока поддерживается создание только узлов элементов, атрибутов, комментариев и текстовых узлов, при чем последние создаются как секции CDATA, что, конечно, является очередным отклонением от стандарта.

Простой конструктор (direct constructor) – это литерал, который создает узел в соответствии с синтаксисом XML. Например, выражение

<a></a>

является вполне допустимым выражением XQuery, которое конструирует узел элемента а. Подобным же образом можно создавать узлы комментариев, текстовые узлы, узлы инструкций обработки и секции CDATA. Например:

(: создание секции CDATA:)<![CDATA[Hi from CDATA!]]> (: создание комментария:)<!--Hi from comment!--> (: Создание текстового узла:)"Hi from text!" (: Создание узла инструкции обработки:)<?target Hi from PI!?>

Что же делать в случае, когда нужно создать атрибут? Ведь нельзя же просто написать:

attr="value"

На помощь приходят вычисляемые конструкторы.

Вычисляемый конструктор узла – это ключевое слово, обозначающее тип узла, за которым следует название узла (если у данного типа узла может быть название) и значение. Значение узла всегда берется в фигурные скобки, внутри которых можно использовать любое выражение XQuery. Если имя узла должно задаваться динамически, его также можно сделать вычисляемым во время исполнения, путем заключения выражения, вычисляющего имя, в фигурные скобки. Например,

(: Создание атрибута а со значением "b":)attribute a {"b"} (: Создание элемента а со значением "b":)element a {"b"} (: Создание фрагмента семья:)element fam{element husband {attribute income {"180"}, "alex"}, element wife {attribute income {"161"}, "rosa"}, element son {attribute income {"90"}, "dima"}}

Вот список всех вычисляемых конструкторов. Их точный синтаксис и использование можно найти в [14].

  • Конструктор элемента (element).
  • Конструктор атрибута (attribute).
  • Конструктор документа (document).
  • Текстовый конструктор (text).
  • Конструктор инструкции обработки (processing-instruction).
  • Конструктор узла комментария (comment).
  • Конструктор узла пространства имен (namespace).

Какие ограничения имеются в реализации SQL Server? Их много. Например, следующий код:

declare @xml xmlset @xml = ''select @xml::query('attribute a {"b"}')

будет выдавать ошибку XQuery: Attribute may not appear outside of an element. По-моему, это сообщение не имеет смысла.

Секция CDATA бесследно исчезает в следующем запросе:

declare @xml xmlset @xml = ''select @xml::query('<![CDATA[Hi from CDATA!]]>')--эквивалентно--declare @xml xml--set @xml = ''--select @xml::query('--"Hi from CDATA"--'</str>)

результат:

Hi from CDATA!--Должно быть--<![CDATA[Hi from CDATA!]]>

Не поддерживаются вычисляемые конструкторы документа, комментария, инструкции обработки, текстового узла и пространства имен.

Кроме этого, мне не удалось использовать ни один конструктор узла с вычисляемым именем: SQL Server упорно выдавал ошибку XQuery: Cannot implicitly convert from 'xs:string' to 'xs:QName'.

Атомарные элементы конструируются с помощью литералов и конструкторов. В XQuery определено четыре типа литерала: строковый литерал (все, что заключено в двойные или одинарные кавычки), целочисленный литерал (целое число), вещественный литерал и литерал с плавающей точкой. Например,

  целочисленный литерал типа xs:interger
10.1 вещественный литерал типа xs:decimal
101E-1 литерал с плавающей точкой типа xs:double
"string" строковый литерал типа xs:string

В выражениях с различными типами операндов выполняется следующее неявное преобразование типов: integer -> decimal -> float -> double.

Если тип операнда после преобразования все же не совместим с типом другого операнда, генерируется ошибка времени компиляции. Тип выражения определяется типом операндов. Например,

1 + 2 выражение типа xs:integer
1 + 2.0 выполняется преобразование литерала 1 до типа xs:double. Тип результата – xs:double
"1" + 1 продвижение выполнить нельзя. Ошибка.

Для конструирования или преобразования типов можно использовать конструкторы атомарных элементов. Конструкторы атомарных элементов – это, по существу, все типы XML Schema. Например,

xs:integer("1") + 1

вполне законное выражение, тип которого xs:integer. Здесь выполняется конструирование типа xs:integer из строкового литерала "1".

ПРИМЕЧАНИЕ Для конструкторов элементов и некоторых встроенных функций разрешается перегрузка по типу операндов. Будем надеяться, эта возможность появится и для пользовательских функций.

Если операнд не может быть преобразован к желаемому типу конструктором, генерируется динамическая ошибка (ошибка времени исполнения).

ПРИМЕЧАНИЕ Это не строгое правило. Если преобразуемое значение задается литералом, процессор может выдать ошибку на этапе компиляции.

Перегруженные конструкторы атомарных элементов фактически являются выражениями преобразования типов и идентичны использованию оператора cast. Следующие строчки эквивалентны:

xs:integer("1") + 1("1" cast as xs:integer) + 1

В XQuery поддерживается также оператор castable, который эквивалентен оператору is в языке VB.NET или в C#. Он возвращает булево значение, равное true, если операнд может быть преобразован к данному типу, и false в противном случае. Например,

if ("1" castable as xs:integer) then "castable"else "not castable"

Возвращает строку castable.

Оператор castable не поддерживается в текущей версии SQL Server. Возможно, он будет реализован в дальнейшем.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: