F.71. xml2
Модуль xml2
предоставляет функции для выполнения запросов XPath и преобразований XSLT.
F.71.1. Уведомление об актуальности
Начиная с PostgreSQL 8.3, функциональность, связанная с XML, основана на стандарте SQL/XML и включена в ядро сервера. Эта функциональность охватывает проверку синтаксиса XML и запросы XPath, что в частности делает и этот модуль, но он имеет абсолютно несовместимый API. Этот модуль планируется удалить в будущей версии Postgres Pro в пользу нового стандартного API, так что мы рекомендуем вам попробовать перевести свои приложения на новый API. Если вы обнаружите, что какая-то функциональность этого модуля не представлена новым API в подходящей форме, пожалуйста, напишите о вашем затруднении в <pgsql-hackers@lists.postgresql.org>
, чтобы этот недостаток был рассмотрен и, возможно, устранён.
F.71.2. Описание функций
Функции, предоставляемые этим модулем, перечислены в Таблице F.131. Эти функции позволяют выполнять простой разбор XML и запросы XPath. Все их аргументы имеют тип text
, поэтому для краткости типы опущены.
Таблица F.131. Функции
Функция | Возвращает | Описание |
---|---|---|
xml_valid(document) | bool | Эта функция разбирает текст документа, переданный в параметре, и возвращает true, если это правильно сформированный XML. (Замечание: это псевдоним стандартной функции Postgres Pro |
xpath_string(document, query) | text | Эти функции обрабатывают запрос XPath для переданного документа и приводят результат к указанному типу. |
xpath_number(document, query) | float4 | |
xpath_bool(document, query) | bool | |
xpath_nodeset(document, query, toptag, itemtag) | text | Эта функция обрабатывает запрос для документа и помещает результат внутрь XML-тегов. Если результат содержит несколько значений, она выдаст: <toptag> <itemtag>Значение 1, которое может быть фрагментом XML</itemtag> <itemtag>Значение 2....</itemtag> </toptag> Если |
xpath_nodeset(document, query) | text | Подобна |
xpath_nodeset(document, query, itemtag) | text | Подобна |
xpath_list(document, query, separator) | text | Эта функция возвращает несколько значений, вставляя между ними заданный разделитель, например: |
xpath_list(document, query) | text | Это обёртка предыдущей функции, устанавливающая в качестве разделителя знак , . |
F.71.3. xpath_table
xpath_table(text key, text document, text relation, text xpaths, text criteria) returns setof record
Табличная функция xpath_table
выполняет набор запросов XPath для каждого из набора документов и возвращает результаты в виде таблицы. В первом столбце результата возвращается первичный ключ из таблицы документов, так что результат оказывается готовым к применению в соединениях. Параметры функции описаны в Таблице F.132.
Таблица F.132. Параметры xpath_table
Параметр | Описание |
---|---|
key | имя «ключевого» поля — содержимое этого поля просто окажется в первом столбце выходной таблицы, то есть оно указывает на запись, из которой была получена определённая выходная строка (см. замечание о нескольких значениях ниже) |
document | имя поля, содержащего XML-документ |
relation | имя таблицы (или представления), содержащей документы |
xpaths | одно или несколько выражений XPath, разделённых символом |
criteria | содержимое предложения WHERE. Оно не может быть пустым, так что если вам нужно обработать все строки в отношении, напишите |
Эти параметры (за исключением строк XPath) просто подставляются в обычный оператор SQL SELECT, так что у вас есть определённая гибкость — оператор выглядит так:
SELECT <key>, <document> FROM <relation> WHERE <criteria>
поэтому в этих параметрах можно передать всё, что будет корректно воспринято в этих позициях. Этот SELECT должен возвращать ровно два столбца (что и будет иметь место, если только вы не перечислите несколько полей в параметрах key или document). Будьте осторожны — при таком примитивном подходе обязательно нужно проверять все значения, получаемые от пользователя, во избежание атак с инъекцией SQL.
Эта функция предназначена для использования в выражении FROM
, с предложением AS
, задающим выходные столбцы; например:
SELECT * FROM xpath_table('article_id', 'article_xml', 'articles', '/article/author|/article/pages|/article/title', 'date_entered > ''2003-01-01'' ') AS t(article_id integer, author text, page_count integer, title text);
Предложение AS
определяет имена и типы столбцов в выходной таблице. Первым определяется «ключевое» поле, а за ним поля, соответствующие запросам XPath. Если запросов XPath больше, чем столбцов в результате, лишние запросы будут игнорироваться. Если же результирующих столбцов больше, чем запросов XPath, дополнительные столбцы принимают значение NULL.
Заметьте, что в этом примере столбец результата page_count
определён как целочисленный. Данная функция внутри имеет дело со строковыми значениями, так что, когда вы указываете, что в результате нужно получить целое число, она берёт текстовое представление результата XPath и, применяя функции ввода Postgres Pro, преобразует её в целое число (или в тот тип, который указан в предложении AS
). Если она не сможет сделать это, произойдёт ошибка — например, если результат пустой — так что если вы допускаете возможность таких проблем с данными, возможно, будет лучше просто оставить для столбца тип text
.
Вызывающий оператор SELECT
не обязательно должен быть простым SELECT *
— он может обращаться к выходным столбцам по именам и соединять их с другими таблицами. Эта функция формирует виртуальную таблицу, с которой вы можете выполнять любые операции, какие пожелаете (например, агрегировать, соединять, сортировать данные и т. д.). Поэтому возможен и такой запрос:
SELECT t.title, p.fullname, p.email FROM xpath_table('article_id', 'article_xml', 'articles', '/article/title|/article/author/@id', 'xpath_string(article_xml,''/article/@date'') > ''2003-03-20'' ') AS t(article_id integer, title text, author_id integer), tblPeopleInfo AS p WHERE t.author_id = p.person_id;
в качестве более сложного примера. Разумеется, для удобства вы можете завернуть весь этот запрос в представление.
F.71.3.1. Результаты с набором значений
Функция xpath_table
рассчитана на то, что результатом каждого запроса XPath может быть набор данных, так что количество возвращённых этой функцией строк может не совпадать с количеством входных документов. В первой строке возвращается первый результат каждого запроса, во второй — второй результат и т. д. Если один из запросов возвращает меньше значений, чем другие, вместо недостающих значений будет возвращаться NULL.
В некоторых случаях пользователь знает, что некоторый запрос XPath будет возвращать только один результат (возможно, уникальный идентификатор документа) — если он используется рядом с запросом XPath, возвращающим несколько результатов, результат с одним значением будет выведен только в первой выходной строке. Чтобы исправить это, можно воспользоваться полем ключа и соединить результат с более простым запросом XPath. Например:
CREATE TABLE test ( id int PRIMARY KEY, xml text ); INSERT INTO test VALUES (1, '<doc num="C1"> <line num="L1"><a>1</a><b>2</b><c>3</c></line> <line num="L2"><a>11</a><b>22</b><c>33</c></line> </doc>'); INSERT INTO test VALUES (2, '<doc num="C2"> <line num="L1"><a>111</a><b>222</b><c>333</c></line> <line num="L2"><a>111</a><b>222</b><c>333</c></line> </doc>'); SELECT * FROM xpath_table('id','xml','test', '/doc/@num|/doc/line/@num|/doc/line/a|/doc/line/b|/doc/line/c', 'true') AS t(id int, doc_num varchar(10), line_num varchar(10), val1 int, val2 int, val3 int) WHERE id = 1 ORDER BY doc_num, line_num id | doc_num | line_num | val1 | val2 | val3 ----+---------+----------+------+------+------ 1 | C1 | L1 | 1 | 2 | 3 1 | | L2 | 11 | 22 | 33
Чтобы получить doc_num
в каждой строке, можно вызывать xpath_table
дважды и соединить результаты:
SELECT t.*,i.doc_num FROM xpath_table('id', 'xml', 'test', '/doc/line/@num|/doc/line/a|/doc/line/b|/doc/line/c', 'true') AS t(id int, line_num varchar(10), val1 int, val2 int, val3 int), xpath_table('id', 'xml', 'test', '/doc/@num', 'true') AS i(id int, doc_num varchar(10)) WHERE i.id=t.id AND i.id=1 ORDER BY doc_num, line_num; id | line_num | val1 | val2 | val3 | doc_num ----+----------+------+------+------+--------- 1 | L1 | 1 | 2 | 3 | C1 1 | L2 | 11 | 22 | 33 | C1 (2 rows)
F.71.4. Функции XSLT
Если установлена libxslt, доступны следующие функции:
F.71.4.1. xslt_process
xslt_process(text document, text stylesheet, text paramlist) returns text
Эта функция применяет стиль XSL к документу и возвращает результат преобразования. В paramlist
передаётся список присваиваний значений параметрам, которые будут использоваться в преобразовании, в форме a=1,b=2
. Учтите, что разбор параметров выполнен очень просто: значения параметров не могут содержать запятые!
Есть также версия xslt_process
с двумя аргументами, которая не передаёт никакие параметры преобразованию.
F.71.5. Автор
Джон Грей <jgray@azuli.co.uk>
Разработку этого модуля спонсировала компания Torchbox Ltd. (www.torchbox.com). Этот модуль выпускается под той же лицензией BSD, что и Postgres Pro.