9.15. Функции XML#

9.15. Функции XML

9.15. Функции XML #

Функции и функциональные выражения, описанные в этом разделе, работают с значениями типа xml. См. Раздел 8.13 для получения информации о типе xml. Функциональные выражения xmlparse и xmlserialize для преобразования в и из типа xml документированы там, а не в этом разделе.

Использование большинства этих функций требует, чтобы Tantor BE был собран с использованием configure --with-libxml.

9.15.1. Производство XML-контента #

Набор функций и функций-подобных выражений доступен для создания XML-контента из данных SQL. Таким образом, они особенно подходят для форматирования результатов запросов в XML-документы для обработки в клиентских приложениях.

9.15.1.1. xmlcomment #

xmlcomment ( text ) → xml

Функция xmlcomment создает значение XML, содержащее комментарий XML с указанным текстом в качестве содержимого. Текст не может содержать -- или заканчиваться на -, иначе полученная конструкция не будет являться допустимым комментарием XML. Если аргумент является пустым, результатом будет также пустое значение.

Пример:

SELECT xmlcomment('hello');

  xmlcomment
--------------
 <!--hello-->

9.15.1.2. xmlconcat #

xmlconcat ( xml [, ...] ) → xml

Функция xmlconcat объединяет список отдельных XML-значений для создания единственного значения, содержащего фрагмент XML-контента. Пустые значения опускаются; результат будет пустым только в случае отсутствия ненулевых аргументов.

Пример:

SELECT xmlconcat('<abc/>', '<bar>foo</bar>');

      xmlconcat
----------------------
 <abc/><bar>foo</bar>

Если присутствуют XML-объявления, они объединяются следующим образом. Если все значения аргументов имеют одно и то же объявление версии XML, то эта версия используется в результате, иначе версия не используется. Если все значения аргументов имеют значение объявления автономности "yes", то это значение используется в результате. Если все значения аргументов имеют значение объявления автономности и по крайней мере одно из них "no", то это значение используется в результате. В противном случае результат не будет содержать объявления автономности. Если определено, что результат требует объявления автономности, но нет объявления версии, будет использовано объявление версии 1.0, поскольку XML требует, чтобы XML-объявление содержало объявление версии. Объявления кодировки игнорируются и удаляются во всех случаях.

Пример:

SELECT xmlconcat('<?xml version="1.1"?><foo/>', '<?xml version="1.1" standalone="no"?><bar/>');

             xmlconcat
-----------------------------------
 <?xml version="1.1"?><foo/><bar/>

9.15.1.3. xmlelement #

xmlelement ( NAME name [, XMLATTRIBUTES ( attvalue [ AS attname ] [, ...] )] [, content [, ...]] ) → xml

Выражение xmlelement создает XML-элемент с указанным именем, атрибутами и содержимым. Показанные в синтаксисе элементы name и attname являются простыми идентификаторами, а не значениями. Элементы attvalue и content являются выражениями, которые могут представлять любой тип данных Tantor BE. Аргумент(ы) внутри XMLATTRIBUTES генерируют атрибуты XML-элемента; значения content объединяются для формирования его содержимого.

Примеры:

SELECT xmlelement(name foo);

 xmlelement
------------
 <foo/>

SELECT xmlelement(name foo, xmlattributes('xyz' as bar));

    xmlelement
------------------
 <foo bar="xyz"/>

SELECT xmlelement(name foo, xmlattributes(current_date as bar), 'cont', 'ent');

             xmlelement
-------------------------------------
 <foo bar="2007-01-26">content</foo>

Имена элементов и атрибутов, которые не являются допустимыми именами XML, экранируются путем замены проблемных символов последовательностью _xHHHH_, где HHHH - это шестнадцатеричное представление кодовой точки символа Unicode. Например:

SELECT xmlelement(name "foo$bar", xmlattributes('xyz' as "a&b"));

            xmlelement
----------------------------------
 <foo_x0024_bar a_x0026_b="xyz"/>

Необходимо указывать явное имя атрибута, если значение атрибута является ссылкой на столбец, в таком случае имя столбца будет использоваться по умолчанию в качестве имени атрибута. В остальных случаях атрибуту должно быть явно указано имя. Таким образом, следующий пример является допустимым:

CREATE TABLE test (a xml, b xml);
SELECT xmlelement(name test, xmlattributes(a, b)) FROM test;

Но это не так:

SELECT xmlelement(name test, xmlattributes('constant'), a, b) FROM test;
SELECT xmlelement(name test, xmlattributes(func(a, b))) FROM test;

Содержимое элемента, если указано, будет отформатировано в соответствии с его типом данных. Если содержимое само по себе имеет тип xml, можно создавать сложные XML-документы. Например:

SELECT xmlelement(name foo, xmlattributes('xyz' as bar),
                            xmlelement(name abc),
                            xmlcomment('test'),
                            xmlelement(name xyz));

                  xmlelement
----------------------------------------------
 <foo bar="xyz"><abc/><!--test--><xyz/></foo>

Содержимое других типов будет отформатировано в допустимые данные XML. Это означает, что символы <, > и & будут преобразованы в сущности. Двоичные данные (тип данных bytea) будут представлены в кодировке base64 или hex, в зависимости от значения параметра конфигурации xmlbinary. Ожидается, что конкретное поведение для отдельных типов данных будет развиваться, чтобы согласовать отображения PostgreSQL с теми, которые указаны в стандарте SQL:2006 и более поздних версиях, как описано в разделе Раздел D.3.1.3.

9.15.1.4. xmlforest #

xmlforest ( content [ AS name ] [, ...] ) → xml

Выражение xmlforest создает XML-лес (последовательность) элементов с использованием указанных имен и содержимого. Что касается xmlelement, каждое name должно быть простым идентификатором, в то время как выражения content могут иметь любой тип данных.

Примеры:

SELECT xmlforest('abc' AS foo, 123 AS bar);

          xmlforest
------------------------------
 <foo>abc</foo><bar>123</bar>


SELECT xmlforest(table_name, column_name)
FROM information_schema.columns
WHERE table_schema = 'pg_catalog';

                                xmlforest
------------------------------------​-----------------------------------
 <table_name>pg_authid</table_name>​<column_name>rolname</column_name>
 <table_name>pg_authid</table_name>​<column_name>rolsuper</column_name>
 ...

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

Имена элементов, которые не являются допустимыми именами XML, экранируются, как показано для xmlelement выше. Аналогично, содержимое данных экранируется для создания допустимого XML-содержимого, если оно не является типом xml.

Обратите внимание, что леса XML не являются допустимыми XML-документами, если они состоят из более чем одного элемента, поэтому может быть полезно обернуть выражения xmlforest в xmlelement.

9.15.1.5. xmlpi #

xmlpi ( NAME name [, content ] ) → xml

Выражение xmlpi создает инструкцию обработки XML. Что касается xmlelement, name должно быть простым идентификатором, а выражение content может иметь любой тип данных. content, если присутствует, не должно содержать последовательность символов ?>.

Пример:

SELECT xmlpi(name php, 'echo "hello world";');

            xmlpi
-----------------------------
 <?php echo "hello world";?>

9.15.1.6. xmlroot #

xmlroot ( xml, VERSION {text|NO VALUE} [, STANDALONE {YES|NO|NO VALUE} ] ) → xml

Выражение xmlroot изменяет свойства корневого узла значения XML. Если указана версия, она заменяет значение в объявлении версии корневого узла; если указано значение для автономного режима, оно заменяет значение в объявлении автономного режима корневого узла.

SELECT xmlroot(xmlparse(document '<?xml version="1.1"?><content>abc</content>'),
               version '1.0', standalone yes);

                xmlroot
----------------------------------------
 <?xml version="1.0" standalone="yes"?>
 <content>abc</content>

9.15.1.7. xmlagg #

xmlagg ( xml ) → xml

Функция xmlagg является, в отличие от других функций, описанных здесь, агрегатной функцией. Она объединяет входные значения в вызове агрегатной функции, подобно тому, как это делает xmlconcat, за исключением того, что объединение происходит между строками, а не между выражениями в одной строке. См. Раздел 9.21 для дополнительной информации об агрегатных функциях.

Пример:

CREATE TABLE test (y int, x xml);
INSERT INTO test VALUES (1, '<foo>abc</foo>');
INSERT INTO test VALUES (2, '<bar/>');
SELECT xmlagg(x) FROM test;
        xmlagg
----------------------
 <foo>abc</foo><bar/>

Для определения порядка конкатенации можно добавить к вызову агрегатной функции предложение ORDER BY, как описано в разделе Раздел 4.2.7. Например:

SELECT xmlagg(x ORDER BY y DESC) FROM test;
        xmlagg
----------------------
 <bar/><foo>abc</foo>

Следующий нестандартный подход ранее рекомендовался, и может быть по-прежнему полезен в определенных случаях:

SELECT xmlagg(x) FROM (SELECT * FROM test ORDER BY y DESC) AS tab;
        xmlagg
----------------------
 <bar/><foo>abc</foo>

9.15.2. Предикаты XML #

Выражения, описанные в этом разделе, проверяют свойства значений типа xml.

9.15.2.1. IS DOCUMENT #

xml IS DOCUMENTboolean

Выражение IS DOCUMENT возвращает true, если аргумент XML-значение является правильным XML-документом, false, если это не так (то есть, это фрагмент содержимого), или null, если аргумент равен null. См. Раздел 8.13 разницу между документами и фрагментами содержимого.

9.15.2.2. IS NOT DOCUMENT #

xml IS NOT DOCUMENTboolean

Выражение IS NOT DOCUMENT возвращает значение false, если аргумент XML является правильным XML-документом, true, если он не является (то есть, это фрагмент содержимого), или null, если аргумент является null.

9.15.2.3. XMLEXISTS #

XMLEXISTS ( text PASSING [BY {REF|VALUE}] xml [BY {REF|VALUE}] ) → boolean

Функция xmlexists выполняет вычисление выражения XPath 1.0 (первый аргумент) с переданным значением XML в качестве контекстного элемента. Функция возвращает false, если результат этой оценки дает пустой набор узлов, и true, если он дает любое другое значение. Функция возвращает null, если любой из аргументов равен null. Ненулевое значение, переданное в качестве контекстного элемента, должно быть XML-документом, а не фрагментом содержимого или любым другим не-XML значением.

Пример:

SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY VALUE '<towns><town>Toronto</town><town>Ottawa</town></towns>');

 xmlexists
------------
 t
(1 row)

Предложения BY REF и BY VALUE принимаются в Tantor BE, но игнорируются, как обсуждалось в Раздел D.3.2.

В стандарте SQL функция xmlexists выполняет выражение на языке запросов XML, но Tantor BE позволяет только выражение XPath 1.0, как описано в Раздел D.3.1.

9.15.2.4. xml_is_well_formed #

xml_is_well_formed ( text ) → boolean
xml_is_well_formed_document ( text ) → boolean
xml_is_well_formed_content ( text ) → boolean

Эти функции проверяют, является ли строка типа text корректным XML и возвращают логический результат. Функция xml_is_well_formed_document проверяет корректность документа, а функция xml_is_well_formed_content проверяет корректность содержимого. Функция xml_is_well_formed выполняет первое, если параметр конфигурации xmloption установлен в DOCUMENT, или второе, если он установлен в CONTENT. Это означает, что функция xml_is_well_formed полезна для проверки успешности простого приведения к типу xml, в то время как другие две функции полезны для проверки успешности соответствующих вариантов XMLPARSE.

Примеры:

SET xmloption TO DOCUMENT;
SELECT xml_is_well_formed('<>');
 xml_is_well_formed
--------------------
 f
(1 row)

SELECT xml_is_well_formed('<abc/>');
 xml_is_well_formed
--------------------
 t
(1 row)

SET xmloption TO CONTENT;
SELECT xml_is_well_formed('abc');
 xml_is_well_formed
--------------------
 t
(1 row)

SELECT xml_is_well_formed_document('<pg:foo xmlns:pg="http://postgresql.org/stuff">bar</pg:foo>');
 xml_is_well_formed_document
-----------------------------
 t
(1 row)

SELECT xml_is_well_formed_document('<pg:foo xmlns:pg="http://postgresql.org/stuff">bar</my:foo>');
 xml_is_well_formed_document
-----------------------------
 f
(1 row)

Последний пример показывает, что проверки включают в себя сопоставление пространств имен.

9.15.3. Обработка XML #

Для обработки значений типа xml PostgreSQL предлагает функции xpath и xpath_exists, которые вычисляют выражения XPath 1.0, а также табличную функцию XMLTABLE.

9.15.3.1. xpath #

xpath ( xpath text, xml xml [, nsarray text[] ] ) → xml[]

Функция xpath выполняет выражение XPath 1.0 xpath (представленное в виде текста) против значения XML xml. Возвращает массив значений XML, соответствующих набору узлов, созданному выражением XPath. Если выражение XPath возвращает скалярное значение, а не набор узлов, возвращается массив с одним элементом.

Второй аргумент должен быть правильно сформированным XML-документом. В частности, он должен иметь единственный корневой элемент узла.

Необязательный третий аргумент функции - это массив пространств имен. Этот массив должен быть двумерным массивом типа text с длиной второй оси, равной 2 (то есть это должен быть массив массивов, каждый из которых состоит ровно из 2 элементов). Первый элемент каждой записи массива - это имя пространства имен (псевдоним), второй - URI пространства имен. Не требуется, чтобы псевдонимы, указанные в этом массиве, совпадали с теми, которые используются в самом XML-документе (другими словами, как в XML-документе, так и в контексте функции xpath, псевдонимы являются локальными).

Пример:

SELECT xpath('/my:a/text()', '<my:a xmlns:my="http://example.com">test</my:a>',
             ARRAY[ARRAY['my', 'http://example.com']]);

 xpath
--------
 {test}
(1 row)

Для работы с пространствами имен по умолчанию (анонимными) можно сделать следующее:

SELECT xpath('//mydefns:b/text()', '<a xmlns="http://example.com"><b>test</b></a>',
             ARRAY[ARRAY['mydefns', 'http://example.com']]);

 xpath
--------
 {test}
(1 row)

9.15.3.2. xpath_exists #

xpath_exists ( xpath text, xml xml [, nsarray text[] ] ) → boolean

Функция xpath_exists является специализированной формой функции xpath. Вместо возвращения отдельных XML-значений, удовлетворяющих выражению XPath 1.0, эта функция возвращает логическое значение, указывающее, был ли выполнен запрос или нет (то есть, было ли получено какое-либо значение, отличное от пустого набора узлов). Эта функция эквивалентна предикату XMLEXISTS, за исключением того, что она также поддерживает аргумент сопоставления пространства имен.

Пример:

SELECT xpath_exists('/my:a/text()', '<my:a xmlns:my="http://example.com">test</my:a>',
                     ARRAY[ARRAY['my', 'http://example.com']]);

 xpath_exists
--------------
 t
(1 row)

9.15.3.3. xmltable #

XMLTABLE (
    [XMLNAMESPACES ( namespace_uri AS namespace_name [, ...] ),]
    row_expression PASSING [BY {REF|VALUE}] document_expression [BY {REF|VALUE}]
    COLUMNS name { type [PATH column_expression] [DEFAULT default_expression] [NOT NULL | NULL]
                  | FOR ORDINALITY }
            [, ...]
) → setof record

Выражение xmltable создает таблицу на основе значения XML, фильтра XPath для извлечения строк и набора определений столбцов. Хотя синтаксически оно напоминает функцию, оно может появляться только в виде таблицы в предложении FROM запроса.

Необязательное предложение XMLNAMESPACES предоставляет список определений пространств имен, разделенных запятыми, где каждый namespace_uri является выражением типа text, а каждый namespace_name - простым идентификатором. Она определяет XML-пространства имен, используемые в документе, и их псевдонимы. Спецификация пространства имен по умолчанию в настоящее время не поддерживается.

Требуемый аргумент row_expression является выражением XPath 1.0 (представленным в виде text), которое вычисляется, передавая XML-значение document_expression в качестве контекстного элемента, для получения набора узлов XML. Эти узлы преобразуются в выходные строки xmltable. Если document_expression равно null или если row_expression возвращает пустой набор узлов или любое значение, отличное от набора узлов, то не будет сгенерировано ни одной строки.

document_expression предоставляет контекстный элемент для row_expression. Он должен быть правильно сформированным XML-документом; фрагменты/леса не принимаются. предложения BY REF и BY VALUE принимаются, но игнорируются, как описано в Раздел D.3.2.

В стандарте SQL функция xmltable выполняет выражения на языке запросов XML, но Tantor BE позволяет использовать только выражения XPath 1.0, как описано в разделе Раздел D.3.1.

Требуется указать предложение COLUMNS, которая определяет столбцы, которые будут созданы в выходной таблице. См. сводку синтаксиса выше для формата. Для каждого столбца требуется указать имя и тип данных (если не указана предложение FOR ORDINALITY, в этом случае тип integer подразумевается неявно). предложения пути, значения по умолчанию и возможности отсутствуют.

Столбец, помеченный FOR ORDINALITY, будет заполнен номерами строк, начиная с 1, в порядке извлечения узлов из результирующего набора узлов row_expression. Только один столбец может быть помечен как FOR ORDINALITY.

Примечание

XPath 1.0 не указывает порядок узлов в наборе узлов, поэтому код, который полагается на определенный порядок результатов, будет зависеть от реализации. Подробности можно найти в Раздел D.3.1.2.

Значение column_expression для столбца представляет собой выражение XPath 1.0, которое вычисляется для каждой строки с текущим узлом из результата row_expression в качестве контекстного элемента, чтобы найти значение столбца. Если не указано выражение column_expression, то имя столбца используется в качестве неявного пути.

Если выражение XPath столбца возвращает значение, не являющееся XML (что ограничено строкой, логическим или числом в XPath 1.0), и столбец имеет тип PostgreSQL, отличный от xml, столбец будет установлен так, как если бы значение было присвоено строковому представлению типа PostgreSQL. (Если значение является логическим, его строковое представление считается 1 или 0, если категория типа выходного столбца является числовой, в противном случае true или false).

Если выражение XPath столбца возвращает непустой набор узлов XML, и тип столбца PostgreSQL - xml, столбцу будет назначен точный результат выражения, если он имеет форму документа или содержимого. [8]

Результат, не являющийся XML, присвоенный столбцу вывода типа xml, производит содержимое, один текстовый узел со строковым значением результата. Если XML-результат присваивается столбцу любого другого типа, то он не может иметь более одного узла, иначе возникает ошибка. Если есть ровно один узел, то столбец будет установлен, как если бы было присвоено строковое значение узла (как определено для функции string XPath 1.0) для типа PostgreSQL.

Значение строки элемента XML является конкатенацией, в порядке документа, всех текстовых узлов, содержащихся в этом элементе и его наследниках. Значение строки элемента без наследников текстовых узлов является пустой строкой (а не NULL). Любые атрибуты xsi:nil игнорируются. Обратите внимание, что узел text(), содержащий только пробельные символы, между двумя не-текстовыми элементами сохраняется, и что ведущие пробелы в узле text() не сглаживаются. Для определения значения строки других типов узлов XML и не-XML значений можно обратиться к функции string XPath 1.0.

Правила преобразования, представленные здесь, не совсем соответствуют стандарту SQL, как обсуждалось в Раздел D.3.1.3.

Если выражение пути возвращает пустой набор узлов (обычно, когда оно не соответствует) для данной строки, то столбец будет установлен в NULL, если не указано default_expression; в этом случае будет использовано значение, полученное при вычислении этого выражения.

A default_expression, вместо того чтобы быть вычисленным немедленно при вызове xmltable, вычисляется каждый раз, когда требуется значение по умолчанию для столбца. Если выражение является стабильным или постоянным, повторное вычисление может быть не указано. Это означает, что вы можете полезно использовать волатильные функции, такие как nextval в default_expression.

Столбцы могут быть помечены как NOT NULL. Если column_expression для столбца NOT NULL не соответствует ничему, и нет DEFAULT или default_expression также вычисляется как null, то будет выдана ошибка.

Примеры:

CREATE TABLE xmldata AS SELECT
xml $$
<ROWS>
  <ROW id="1">
    <COUNTRY_ID>AU</COUNTRY_ID>
    <COUNTRY_NAME>Australia</COUNTRY_NAME>
  </ROW>
  <ROW id="5">
    <COUNTRY_ID>JP</COUNTRY_ID>
    <COUNTRY_NAME>Japan</COUNTRY_NAME>
    <PREMIER_NAME>Shinzo Abe</PREMIER_NAME>
    <SIZE unit="sq_mi">145935</SIZE>
  </ROW>
  <ROW id="6">
    <COUNTRY_ID>SG</COUNTRY_ID>
    <COUNTRY_NAME>Singapore</COUNTRY_NAME>
    <SIZE unit="sq_km">697</SIZE>
  </ROW>
</ROWS>
$$ AS data;

SELECT xmltable.*
  FROM xmldata,
       XMLTABLE('//ROWS/ROW'
                PASSING data
                COLUMNS id int PATH '@id',
                        ordinality FOR ORDINALITY,
                        "COUNTRY_NAME" text,
                        country_id text PATH 'COUNTRY_ID',
                        size_sq_km float PATH 'SIZE[@unit = "sq_km"]',
                        size_other text PATH
                             'concat(SIZE[@unit!="sq_km"], " ", SIZE[@unit!="sq_km"]/@unit)',
                        premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified');

 id | ordinality | COUNTRY_NAME | country_id | size_sq_km |  size_other  | premier_name
----+------------+--------------+------------+------------+--------------+---------------
  1 |          1 | Australia    | AU         |            |              | not specified
  5 |          2 | Japan        | JP         |            | 145935 sq_mi | Shinzo Abe
  6 |          3 | Singapore    | SG         |        697 |              | not specified

Следующий пример показывает конкатенацию нескольких узлов text(), использование имени столбца в качестве фильтра XPath и обработку пробелов, XML-комментариев и инструкций обработки:

CREATE TABLE xmlelements AS SELECT
xml $$
  <root>
   <element>  Hello<!-- xyxxz -->2a2<?aaaaa?> <!--x-->  bbb<x>xxx</x>CC  </element>
  </root>
$$ AS data;

SELECT xmltable.*
  FROM xmlelements, XMLTABLE('/root' PASSING data COLUMNS element text);
         element
-------------------------
   Hello2a2   bbbxxxCC

Следующий пример иллюстрирует, как можно использовать предложение XMLNAMESPACES для указания списка пространств имен, используемых в XML-документе, а также в выражениях XPath:

WITH xmldata(data) AS (VALUES ('
<example xmlns="http://example.com/myns" xmlns:B="http://example.com/b">
 <item foo="1" B:bar="2"/>
 <item foo="3" B:bar="4"/>
 <item foo="4" B:bar="5"/>
</example>'::xml)
)
SELECT xmltable.*
  FROM XMLTABLE(XMLNAMESPACES('http://example.com/myns' AS x,
                              'http://example.com/b' AS "B"),
             '/x:example/x:item'
                PASSING (SELECT data FROM xmldata)
                COLUMNS foo int PATH '@foo',
                  bar int PATH '@B:bar');
 foo | bar
-----+-----
   1 |   2
   3 |   4
   4 |   5
(3 rows)

9.15.4. Сопоставление таблиц с XML #

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

table_to_xml ( table regclass, nulls boolean,
               tableforest boolean, targetns text ) → xml
query_to_xml ( query text, nulls boolean,
               tableforest boolean, targetns text ) → xml
cursor_to_xml ( cursor refcursor, count integer, nulls boolean,
                tableforest boolean, targetns text ) → xml

table_to_xml отображает содержимое указанной таблицы, переданной в качестве параметра table. Тип regclass принимает строки, идентифицирующие таблицы с использованием обычного синтаксиса, включая опциональную квалификацию схемы и двойные кавычки (см. Раздел 8.19 для получения подробной информации). query_to_xml выполняет запрос, текст которого передается в качестве параметра query, и отображает результат. cursor_to_xml извлекает указанное количество строк из курсора, указанного параметром cursor. Этот вариант рекомендуется, если требуется отобразить большие таблицы, поскольку каждая функция строит результат в памяти.

Если tableforest равно false, то результирующий XML-документ будет выглядеть так:

<tablename>
  <row>
    <columnname1>data</columnname1>
    <columnname2>data</columnname2>
  </row>

  <row>
    ...
  </row>

  ...
</tablename>

Если параметр tableforest установлен в true, результатом будет фрагмент XML-контента, который выглядит следующим образом:

<tablename>
  <columnname1>data</columnname1>
  <columnname2>data</columnname2>
</tablename>

<tablename>
  ...
</tablename>

...

Если имя таблицы недоступно, то есть при отображении запроса или курсора, в первом формате используется строка table, а во втором формате - row.

Выбор между этими форматами остается за пользователем. Первый формат представляет собой правильный XML-документ, что может быть важным во многих приложениях. Второй формат обычно более полезен в функции cursor_to_xml, если значения результата должны быть впоследствии собраны в один документ. Функции для создания XML-содержимого, обсуждаемые выше, в частности xmlelement, могут быть использованы для изменения результатов по вкусу.

Данные значения отображаются так же, как описано для функции xmlelement выше.

Параметр nulls определяет, должны ли включаться в вывод значения null. Если значение true, то значения null в столбцах представлены как:

<columnname xsi:nil="true"/>

где xsi - это префикс пространства имен XML для XML Schema Instance. В результате будет добавлено соответствующее объявление пространства имен. Если значение false, столбцы, содержащие пустые значения, просто опускаются из вывода.

Параметр targetns определяет желаемое XML-пространство имен результата. Если не требуется конкретное пространство имен, следует передать пустую строку.

Следующие функции возвращают документы XML Schema, описывающие отображения, выполняемые соответствующими вышеуказанными функциями:

table_to_xmlschema ( table regclass, nulls boolean,
                     tableforest boolean, targetns text ) → xml
query_to_xmlschema ( query text, nulls boolean,
                     tableforest boolean, targetns text ) → xml
cursor_to_xmlschema ( cursor refcursor, nulls boolean,
                      tableforest boolean, targetns text ) → xml

Необходимо передавать одни и те же параметры, чтобы получить соответствующие отображения данных XML и документы XML Schema.

Следующие функции создают отображения данных XML и соответствующую XML-схему в одном документе (или лесу), связанные вместе. Они могут быть полезны, когда требуются автономные результаты и результаты с самоописанием.

table_to_xml_and_xmlschema ( table regclass, nulls boolean,
                             tableforest boolean, targetns text ) → xml
query_to_xml_and_xmlschema ( query text, nulls boolean,
                             tableforest boolean, targetns text ) → xml

Кроме того, доступны следующие функции для создания аналогичных отображений всей схемы или всей текущей базы данных:

schema_to_xml ( schema name, nulls boolean,
                tableforest boolean, targetns text ) → xml
schema_to_xmlschema ( schema name, nulls boolean,
                      tableforest boolean, targetns text ) → xml
schema_to_xml_and_xmlschema ( schema name, nulls boolean,
                              tableforest boolean, targetns text ) → xml

database_to_xml ( nulls boolean,
                  tableforest boolean, targetns text ) → xml
database_to_xmlschema ( nulls boolean,
                        tableforest boolean, targetns text ) → xml
database_to_xml_and_xmlschema ( nulls boolean,
                                tableforest boolean, targetns text ) → xml

Эти функции игнорируют таблицы, которые не доступны для чтения текущим пользователем. Функции, применяемые к всей базе данных, также игнорируют схемы, для которых текущий пользователь не имеет привилегии USAGE (поиск).

Обратите внимание, что это потенциально может создать большой объем данных, который нужно будет накапливать в памяти. При запросе сопоставлений содержимого больших схем или баз данных, может быть целесообразно рассмотреть отдельное сопоставление таблиц, возможно, даже через курсор.

Результат сопоставления содержимого схемы выглядит следующим образом:

<schemaname>

table1-mapping

table2-mapping

...

</schemaname>

где формат отображения таблицы зависит от параметра tableforest, как объяснено выше.

Результат отображения содержимого базы данных выглядит следующим образом:

<dbname>

<schema1name>
  ...
</schema1name>

<schema2name>
  ...
</schema2name>

...

</dbname>

где сопоставление схемы такое, как указано выше.

В качестве примера использования вывода, созданного этими функциями, Пример 9.1 показывает таблицу стилей XSLT, которая преобразует вывод функции table_to_xml_and_xmlschema в HTML-документ, содержащий табличное представление данных таблицы. Аналогичным образом результаты этих функций могут быть преобразованы в другие форматы на основе XML.

Пример 9.1. XSLT Стиль для преобразования SQL/XML вывода в HTML

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="http://www.w3.org/1999/xhtml"
>

  <xsl:output method="xml"
      doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
      doctype-public="-//W3C/DTD XHTML 1.0 Strict//EN"
      indent="yes"/>

  <xsl:template match="/*">
    <xsl:variable name="schema" select="//xsd:schema"/>
    <xsl:variable name="tabletypename"
                  select="$schema/xsd:element[@name=name(current())]/@type"/>
    <xsl:variable name="rowtypename"
                  select="$schema/xsd:complexType[@name=$tabletypename]/xsd:sequence/xsd:element[@name='row']/@type"/>

    <html>
      <head>
        <title><xsl:value-of select="name(current())"/></title>
      </head>
      <body>
        <table>
          <tr>
            <xsl:for-each select="$schema/xsd:complexType[@name=$rowtypename]/xsd:sequence/xsd:element/@name">
              <th><xsl:value-of select="."/></th>
            </xsl:for-each>
          </tr>

          <xsl:for-each select="row">
            <tr>
              <xsl:for-each select="*">
                <td><xsl:value-of select="."/></td>
              </xsl:for-each>
            </tr>
          </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>



[8] Результат, содержащий более одного узла верхнего уровня или нетекстовые пробелы вне элемента, является примером формы содержимого. Результат XPath может быть ни одной из этих форм, например, если он возвращает атрибутный узел, выбранный из элемента, который его содержит. Такой результат будет помещен в форму содержимого, при этом каждый такой недопустимый узел будет заменен его строковым значением, как определено для функции XPath 1.0 string.