xml2 模块提供 XPath 查询与 XSLT 功能。
自 PostgreSQL 8.3 起,核心服务器就提供了基于 SQL/XML 标准的 XML 相关功能。该功能覆盖了 XML 语法检查和 XPath 查询,也就是本模块所做的事情,而且能力更多;不过,两者的 API 完全不兼容。计划在未来的 PostgreSQL 版本中移除此模块,转而采用较新的标准 API,因此建议你尝试迁移应用程序。如果你发现本模块的某些功能在较新的 API 中还没有以足够完善的形式提供,请向 <pgsql-hackers@lists.postgresql.org> 说明你的问题,以便补齐这一不足。
Table F.38 显示了该模块提供的函数。这些函数提供简单直接的 XML 解析和 XPath 查询功能。
Table F.38. xml2 函数
|
函数 描述 |
|---|
|
解析给定文档,如果该文档是良构 XML,则返回 true。(注意:这是标准 PostgreSQL 函数 |
|
对给定文档执行 XPath 查询,并将结果转换为 |
|
对给定文档执行 XPath 查询,并将结果转换为 |
|
对给定文档执行 XPath 查询,并将结果转换为 |
|
对文档执行该查询,并将结果包在 XML 标签中。如果结果包含多个值,输出将类似于: <toptag> <itemtag>Value 1 which could be an XML fragment</itemtag> <itemtag>Value 2....</itemtag> </toptag> 如果 |
|
与 |
|
与 |
|
对文档执行该查询,并返回由指定分隔符分隔的多个值;例如当 |
|
这是上一个函数的包装器,使用 |
xpath_table #xpath_table(text key, text document, text relation, text xpaths, text criteria) returns setof record
xpath_table 是一个表函数,它对一组文档中的每个文档执行一组 XPath 查询,并将结果作为表返回。原始文档表中的主键字段会作为结果的第一列返回,因此结果集可以方便地用于连接。参数说明见 Table F.39。
Table F.39. xpath_table 参数
| 参数 | 描述 |
|---|---|
key |
“key” 字段的名称 — 这只是一个作为输出表第一列使用的字段,也就是说,它用于标识每个输出行来自哪条记录(关于多个值,见下文注释) |
document |
包含 XML 文档的字段名 |
relation |
包含这些文档的表或视图名 |
xpaths |
一个或多个 XPath 表达式,用 |
criteria |
|
这些参数(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 子句定义了输出表中各列的名称和类型。第一列是 “key” 字段,其余各列对应 XPath 查询。如果 XPath 查询多于结果列,多出的查询将被忽略。如果结果列多于 XPath 查询,多出的列将为 NULL。
注意,这个示例把 page_count 结果列定义为整数。该函数内部只处理字符串表示,因此当你在输出中声明整数时,它会取 XPath 结果的字符串表示,并使用 PostgreSQL 输入函数将其转换为整数(或者 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;
当然,出于方便,你也可以把这一切封装到一个视图中。
xpath_table 函数假定每个 XPath 查询的结果都可能有多个值,因此该函数返回的行数可能不同于输入文档的数量。返回的第一行包含每个查询的第一个结果,第二行包含每个查询的第二个结果。如果某个查询的值少于其他查询,则会在相应位置返回空值。
在某些情况下,用户会知道某个 XPath 查询只会返回单个结果(例如唯一文档标识符)— 如果它与返回多个结果的 XPath 查询一起使用,这个单值结果只会出现在结果的第一行。解决办法是把 key 字段作为与一个更简单的 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)
如果安装了 libxslt,则可使用下列函数:
xslt_process #xslt_process(text document, text stylesheet, text paramlist) returns text
这个函数将 XSL 样式表应用到文档上,并返回转换后的结果。paramlist 是转换时要使用的参数赋值列表,以 a=1,b=2 的形式指定。注意,参数解析非常简单:参数值中不能包含逗号!
此外还有 xslt_process 的双参数版本,它不会向转换传递任何参数。
John Gray <jgray@azuli.co.uk>
本模块由 Torchbox Ltd. (www.torchbox.com) 赞助开发。它采用与 PostgreSQL 相同的 BSD 许可证。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。