9.15. XML-функции
Функции и подобные им выражения, описанные в этом разделе, работают со значениями типа xml
. Информацию о типе xml
вы можете найти в Разделе 8.13. Подобные функциям выражения xmlparse
и xmlserialize
, преобразующие значения xml
в текст и обратно, здесь повторно не рассматриваются.
Для использования этих функций PostgreSQL нужно задействовать соответствующую библиотеку при сборке: configure --with-libxml
.
9.15.1. Создание XML-контента
Для получения XML-контента из данных SQL существует целый набор функций и функциональных выражений, особенно полезных для выдачи клиентским приложениям результатов запроса в виде XML-документов.
9.15.1.1. xmlcomment
xmlcomment
(text
) →xml
Функция xmlcomment
создаёт XML-значение, содержащее XML-комментарий с заданным текстом. Этот текст не должен содержать «--
» или заканчиваться знаком «-
», в противном случае результат не будет допустимым XML-комментарием. Если аргумент этой функции NULL, результатом её тоже будет NULL.
Пример:
SELECT xmlcomment('hello'); xmlcomment -------------- <!--hello-->
9.15.1.2. xmlconcat
xmlconcat
(xml
[, ...] ) →xml
Функция xmlconcat
объединяет несколько XML-значений и выдаёт в результате один фрагмент XML-контента. Значения NULL отбрасываются, так что результат будет равен NULL, только если все аргументы равны NULL.
Пример:
SELECT xmlconcat('<abc/>', '<bar>foo</bar>'); xmlconcat ---------------------- <abc/><bar>foo</bar>
XML-объявления, если они присутствуют, обрабатываются следующим образом. Если во всех аргументах содержатся объявления одной версии XML, эта версия будет выдана в результате; в противном случае версии не будет. Если во всех аргументах определён атрибут standalone со значением «yes», это же значение будет выдано в результате. Если во всех аргументах есть объявление standalone, но минимум в одном со значением «no», в результате будет это значение. В противном случае в результате не будет объявления standalone. Если же окажется, что в результате должно присутствовать объявление standalone, а версия не определена, тогда в результате будет выведена версия 1.0, так как 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
имя
[,XMLATTRIBUTES
(значение_атрибута
[AS
атрибут
] [, ...] )] [,содержимое
[, ...]] ) →xml
Выражение xmlelement
создаёт XML-элемент с заданным именем, атрибутами и содержимым. Аргументы имя
и значение_атрибута
, показанные в синтаксисе, обозначают простые идентификаторы, а не определённые значения. Аргументы значение_атрибута
и содержимое
являются выражениями, которые могут выдавать любой тип данных PostgreSQL. Аргументы внутри XMLATTRIBUTES
генерируют атрибуты XML-элемента, к которому также добавляются значения содержимое
, в итоге формируя его содержимое.
Примеры:
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, эти символы заменяются последовательностями _x
, где HHHH
_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. Это, в частности, означает, что символы <, > и & будут преобразованы в сущности XML. Двоичные данные (данные типа bytea
) представляются в кодировке base64 или в шестнадцатеричном виде, в зависимости от значения параметра xmlbinary. Следует ожидать, что конкретные представления отдельных типов данных могут быть изменены для приведения преобразований PostgreSQL в соответствие со стандартом SQL:2006 и новее, как описано в Подразделе D.3.1.3.
9.15.1.4. xmlforest
xmlforest
(содержимое
[AS
имя
] [, ...] ) →xml
Выражение xmlforest
создаёт последовательность XML-элементов с заданными именами и содержимым. Как и в функции xmlelement
, каждый аргумент имя
должен быть простым идентификатором, а выражения содержимое
могут иметь любой тип данных.
Примеры:
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
имя
[,содержимое
] ) →xml
Выражение xmlpi
создаёт инструкцию обработки XML. Как и в функции xmlelement
, аргумент имя
должен быть простым идентификатором, а выражения содержимое
могут иметь любой тип данных. Содержимое, если оно задано, не должно содержать последовательность символов ?>
.
Пример:
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-значения. Если в нём указывается версия, она заменяет значение в объявлении версии корневого узла; также в корневой узел переносится значение свойства standalone.
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 DOCUMENT
→boolean
Выражение IS DOCUMENT
возвращает true, если аргумент представляет собой правильный XML-документ, false в противном случае (т. е. если это фрагмент содержимого) и NULL, если его аргумент также NULL. Чем документы отличаются от фрагментов содержимого, вы можете узнать в Разделе 8.13.
9.15.2.2. IS NOT DOCUMENT
xml
IS NOT DOCUMENT
→boolean
Выражение IS NOT DOCUMENT
возвращает false, если аргумент представляет собой правильный 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. Отличный от 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
в PostgreSQL принимаются, но игнорируются, о чём рассказывается в Подразделе D.3.2.
Согласно стандарту SQL, функция xmlexists
должна вычислять выражение, используя средства языка XML Query, но PostgreSQL воспринимает только выражения 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
Эти функции проверяют, представляет ли текст
правильно оформленный 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
(uri_пространства_имён
AS
имя_пространства_имён
[, ...] ),]выражение_строки
PASSING
[BY
{REF
|VALUE
}]выражение_документа
[BY
{REF
|VALUE
}]COLUMNS
имя
{тип
[PATH
выражение_столбца
] [DEFAULT
выражение_по_умолчанию
] [NOT NULL
|NULL
] |FOR ORDINALITY
} [, ...] ) →setof record
Выражение xmltable
строит таблицу из XML-значения, применяя фильтр XPath для извлечения строк и формируя столбцы с заданным определением. Хотя по синтаксису оно подобно функции, оно может применяться только в качестве таблицы в предложении FROM
.
Необязательное предложение XMLNAMESPACES
задаёт разделённый запятыми список определений пространств имён, в котором uri_пространства_имён
— выражение типа text
, а имя_пространства_имён
— простой идентификатор. В нём определяются пространства имён XML, используемые в документе, и их псевдонимы. Определение пространства по умолчанию в настоящее время не поддерживается.
В обязательном аргументе выражение_строки
передаётся выражение XPath 1.0 (в виде значения text
), которое будет вычисляться для XML-значения выражение_документа
, служащего элементом контекста, и выдавать набор узлов XML. Эти узлы xmltable
преобразует в выходные строки. Если выражение_документа
— NULL, а также если выражение_строки
выдаёт пустой набор узлов или любое значение, отличное от набора узлов, выходные строки не выдаются.
Выражение_документа
передаёт элемент контекста для выражения_строки
. Таким элементом должен быть правильно оформленный XML-документ; фрагменты/наборы деревьев не допускаются. Предложения BY REF
и BY VALUE
принимаются, но игнорируются, о чём рассказывается в Подразделе D.3.2.
Согласно стандарту SQL, функция xmltable
должна вычислять выражения, используя средства языка XML Query, но PostgreSQL воспринимает только выражения XPath 1.0; подробнее об этом говорится в Подразделе D.3.1.
В обязательном предложении COLUMNS
задаётся список столбцов для выходной таблицы. Формат этого предложения показан выше в описании синтаксиса. Для каждого столбца должно задаваться имя и тип данных (если только не указано FOR ORDINALITY
, что подразумевает тип integer
). Путь, значение по умолчанию и признак допустимости NULL могут опускаться.
Столбец с признаком FOR ORDINALITY
будет заполняться номерами строк, начиная с 1, в том порядке, в котором эти строки идут в наборе узлов, представляющем результат выражения_строки
. Признак FOR ORDINALITY
может быть не больше чем у одного столбца.
Примечание
В XPath 1.0 не определён порядок узлов в наборе, поэтому код, рассчитывающий на определённый порядок результатов, будет зависеть от конкретной реализации. Подробнее об этом рассказывается в Подразделе D.3.1.2.
В выражении_столбца
задаётся выражение XPath 1.0, которое вычисляется для каждой строки применительно к текущему узлу, полученному в результате вычисления выражения_строки
и служащему элементом контекста, и выдаёт значение столбца. Если выражение_столбца
отсутствует, в качестве неявного пути используется имя столбца.
Если выражение XPath возвращает не XML (это может быть строка, логическое или числовое значение в XPath 1.0) и столбец имеет тип PostgreSQL, отличный от xml
, значение присваивается столбцу так же, как типу PostgreSQL присваивается строковое представление значения. (Если это значение логическое, его строковым представлением будет 1
или 0
, если тип столбца относится к числовой категории, и true
или false
в противном случае.)
Если заданное для столбца выражение XPath возвращает непустой набор узлов XML и этот столбец в PostgreSQL имеет тип xml
, значение ему будет присвоено как есть, когда оно имеет форму документа или содержимого. [8]
Когда выходному столбцу xml
присваивается не XML-содержимое, оно представляется в виде одного текстового узла, содержащего строковое значение результата. XML-результат, присваиваемый столбцу любого другого типа, должен состоять не более чем из одного узла, иначе выдаётся ошибка. При наличии же ровно одного узла столбцу, с учётом его типа PostgreSQL, присваивается строковое представление этого узла (получаемое по правилам функции string
в XPath 1.0).
Строковым значением XML-элемента является конкатенация всех текстовых узлов, содержащихся в нём и во вложенных в него элементах, в порядке следования этих узлов в документе. Строковым значением элемента без внутренних текстовых узлов является пустая строка (не NULL
). Любые атрибуты со свойствами xsi:nil
игнорируются. Заметьте, что состоящий только из пробельных символов узел text()
между двумя нетекстовыми элементами при этом сохраняется, и начальные пробелы в узле text()
не убираются. Правила, определяющие строковые представления для других типов XML-узлов и не XML-значений, можно найти в описании функции string
языка XPath 1.0.
Представленные здесь правила преобразования не соответствуют в точности тем, что определены в стандарте SQL, о чём рассказывается в Подразделе D.3.1.3.
Когда выражение пути возвращает для данной строки пустой набор узлов (обычно когда нет соответствия этому пути), столбец получает значение NULL
, если только не задано выражение_по_умолчанию
. Если же оно задано, столбец получает результат данного выражения.
Указанное выражение_по_умолчанию
вычисляется не единожды для вызова функции xmltable
, а каждый раз, когда для столбца требуется очередное значение по умолчанию. Если же это выражение оказывается стабильным или постоянным, повторное вычисление может не выполняться. Это означает, что в выражении_по_умолчанию
вы можете с пользой применять изменчивые функции, такие как nextval
.
Столбцы могут иметь признак NOT NULL
. Если выражение_столбца
для столбца с признаком NOT NULL
не соответствует ничему и при этом отсутствует указание DEFAULT
или выражение_по_умолчанию
также выдаёт 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
отображает в xml содержимое таблицы, имя которой задаётся в параметре table
. Тип regclass
принимает идентификаторы строк в обычной записи, которые могут содержать указание схемы и кавычки (за подробностями обратитесь к Разделу 8.19). Функция query_to_xml
выполняет запрос, текст которого передаётся в параметре query
, и отображает в xml результирующий набор. Последняя функция, cursor_to_xml
выбирает указанное число строк из курсора, переданного в параметре cursor
. Этот вариант рекомендуется использовать с большими таблицами, так как все эти функции создают результирующий xml в памяти.
Если параметр tableforest
имеет значение false, результирующий XML-документ выглядит так:
<имя_таблицы> <row> <имя_столбца1> данные </имя_столбца1> <имя_столбца2> данные </имя_столбца2> </row> <row> ... </row> ... </имя_таблицы>
А если tableforest
равен true, в результате будет выведен следующий фрагмент XML:
<имя_таблицы> <имя_столбца1> данные </имя_столбца1> <имя_столбца2> данные </имя_столбца2> </имя_таблицы> <имя_таблицы> ... </имя_таблицы> ...
Если имя таблицы неизвестно, например, при отображении результатов запроса или курсора, вместо него в первом случае вставляется table
, а во втором — row
.
Выбор между этими форматами остаётся за пользователем. Первый вариант позволяет создать готовый XML-документ, что может быть полезно для многих приложений, а второй удобно применять с функцией cursor_to_xml
, если её результаты будут собираться в документ позже. Полученный результат можно изменить по вкусу с помощью рассмотренных выше функций создания XML-содержимого, в частности xmlelement
.
Значения данных эти функции отображают так же, как и ранее описанная функция xmlelement
.
Параметр nulls
определяет, нужно ли включать в результат значения NULL. Если он установлен, значения NULL в столбцах представляются так:
<имя_столбца xsi:nil="true"/>
Здесь xsi
— префикс пространства имён XML Schema Instance. При этом в результирующий XML будет добавлено соответствующее объявление пространства имён. Если же данный параметр равен false, столбцы со значениями NULL просто не будут выводиться.
Параметр 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-схемам, важно, чтобы соответствующим функциям передавались одинаковые параметры.
Следующие функции выдают отображение данных в 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
).
Заметьте, что объём таких данных может быть очень большим, а XML должен сформироваться в памяти. Поэтому, вместо того чтобы пытаться отобразить в XML сразу всё содержимое больших схем или баз данных, лучше делать это по таблицам, возможно, даже используя курсор.
Результат отображения содержимого схемы будет выглядеть так:
<имя_схемы> отображение-таблицы1 отображение-таблицы2 ... </имя_схемы>
Формат отображения таблицы определяется параметром tableforest
, описанным выше.
Результат отображения содержимого базы данных будет таким:
<имя_БД> <имя_схемы1> ... </имя_схемы1> <имя_схемы2> ... </имя_схемы2> ... </имя_БД>
Здесь отображение схемы имеет вид, показанный выше.
В качестве примера, иллюстрирующего использование результата этих функций, на Примере 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 может иметь и другую форму, например, если оно выбирает узел атрибута из содержащего этот атрибут элемента. Такой результат будет приведён в форму содержимого, в которой каждый подобный недопустимый узел заменяется строковым представлением, получаемым по правилам функции string
в XPath 1.0.