pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
本节中描述的函数以及类函数表达式都作用于类型xml的值。关于xml类型的信息请查阅第 8.13 节。用于与xml类型相互转换的类函数表达式xmlparse和xmlserialize不在此重复。使用这些函数中的大多数要求安装时使用configure --with-libxml编译。
有一组函数和类函数的表达式可以用来从 SQL 数据产生 XML 内容。它们特别适合于将查询结果格式化成 XML 文档以便于在客户端应用中处理。
xmlcommentxmlcomment(text)
函数 xmlcomment 创建一个 XML 值,其中包含以指定文本为内容的 XML 注释。该文本不能包含 “--”,也不能以 “-” 结尾,以确保构造出的 XML 注释有效。如果参数为空值,结果也为空值。
示例:
SELECT xmlcomment('hello');
xmlcomment
--------------
<!--hello-->
xmlconcatxmlconcat(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/>
xmlelementxmlelement(namename[, xmlattributes(value[ASattname] [, ... ])] [, content, ...])
表达式 xmlelement 使用给定的名称、属性和内容生成一个 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 字符数据。这意味着字符 <, >, 和 & 将被转换为实体。二进制数据(数据类型bytea)将被表示成 base64 或十六进制编码,具体取决于配置参数xmlbinary的设置。个别数据类型的特殊行为将不断发展,以使SQL和PostgreSQL数据类型与 XML Schema 规范对齐,届时将给出更精确的描述。
xmlforestxmlforest(content[ASname] [, ...])
表达式 xmlforest 使用给定的名称和内容生成由元素构成的 XML 森林(序列)。
示例:
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>
...
如第二个示例所示,如果内容值是一个列引用,可以省略元素名称,此时默认使用列名。否则,必须指定名称。
如上文xmlelement所示,非法 XML 名字的元素名会被转义。相似地,内容数据也会被转义来产生合法的 XML 内容,除非它已经是一个xml类型。
注意如果 XML 森林由多于一个元素组成,那么它不是合法的 XML 文档,因此在xmlelement中包装xmlforest表达式会有用处。
xmlpixmlpi(nametarget[,content])
表达式 xmlpi 创建一个 XML 处理指令。如果提供了内容,其中不得包含字符序列 ?>。
示例:
SELECT xmlpi(name php, 'echo "hello world";');
xmlpi
-----------------------------
<?php echo "hello world";?>
xmlrootxmlroot(xml, versiontext| no value [, standalone yes|no|no value])
表达式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>
xmlagg #xmlagg(xml)
和这里描述的其他函数不同,函数xmlagg是一个聚合函数。它将聚合函数调用的输入值串接起来,非常像xmlconcat所做的事情,除了串接是跨行发生的而不是在单一行的多个表达式上发生。聚合表达式的更多信息请见第 9.18 节。
示例:
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>
xml IS DOCUMENT
如果参数 XML 值是一个正确的 XML 文档,则IS DOCUMENT返回真,如果不是则返回假(即它是一个内容片断),或者是参数为空时返回空。文档和内容片断之间的区别请见第 8.13 节。
为了处理xml数据类型的值,PostgreSQL提供了xpath函数,它计算 XPath 1.0 表达式。
xpath(xpath,xml[,nsarray])
函数xpath针对 XML 值xml计算 XPath 表达式xpath。它返回一个由 XPath 表达式产生的节点集所对应的 XML 值组成的数组。
第二个参数必须是一个良构的 XML 文档。特殊地,它必须有一个单一根结点元素。
该函数的第三个参数是一个名字空间映射的数组。这个数组应该是一个二维数组,其第二轴长度等于 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)
以下函数将关系表的内容映射为 XML 值,可以将它们视为 XML 导出功能:
table_to_xml(tbl regclass, nulls boolean, tableforest boolean, targetns text)
query_to_xml(query text, nulls boolean, tableforest boolean, targetns text)
cursor_to_xml(cursor refcursor, count int, nulls boolean,
tableforest boolean, targetns text)
每个函数的返回类型都是xml。
table_to_xml映射由参数tbl传递的命名表的内容。 regclass类型接受使用常见标记标识表的字符串,包括可选的模式限定和双引号。 query_to_xml执行由参数query传递的查询并且映射结果集。 cursor_to_xml从cursor指定的游标中取出指定数量的行。 如果需要映射一个大型的表,我们推荐这种变体,因为每一个函数都是在内存中构建结果值的。
如果tableforest为假,则结果的 XML 文档看起来像这样:
<tablename>
<row>
<columnname1>data</columnname1>
<columnname2>data</columnname2>
</row>
<row>
...
</row>
...
</tablename>
如果tableforest为真,结果是一个看起来像这样的 XML 内容片断:
<tablename> <columnname1>data</columnname1> <columnname2>data</columnname2> </tablename> <tablename> ... </tablename> ...
如果没有表名可用,在映射一个查询或一个游标时,在第一种格式中使用串table,在第二种格式中使用row。
这几种格式的选择由用户决定。第一种格式是一个正确的 XML 文档,它在很多应用中都很重要。如果结果值要被重组为一个文档,第二种格式在cursor_to_xml函数中更有用。前文讨论的产生 XML 内容的函数(特别是xmlelement)可以被用来把结果修改成符合用户的要求。
数据值会被以前文的函数xmlelement中描述的相同方法映射。
参数nulls决定空值是否会被包含在输出中。如果为真,列中的空值被表示为:
<columnname xsi:nil="true"/>
其中xsi是 XML 模式实例的 XML 名字空间前缀。一个合适的名字空间声明将被加入到结果值中。如果为假,包含空值的列将被从输出中忽略掉。
参数targetns指定想要的结果的 XML 名字空间。如果没有想要的特定名字空间,将会传递一个空串。
以下函数返回 XML Schema 文档,描述上面相应函数所执行的映射:
table_to_xmlschema(tbl regclass, nulls boolean, tableforest boolean, targetns text) query_to_xmlschema(query text, nulls boolean, tableforest boolean, targetns text) cursor_to_xmlschema(cursor refcursor, nulls boolean, tableforest boolean, targetns text)
必须传入相同的参数,才能得到彼此匹配的 XML 数据映射和 XML Schema 文档。
以下函数在同一个文档(或森林)中生成 XML 数据映射和对应的 XML Schema,并将两者链接在一起。当需要自包含且自描述的结果时,这些函数很有用:
table_to_xml_and_xmlschema(tbl regclass, nulls boolean, tableforest boolean, targetns text) query_to_xml_and_xmlschema(query text, nulls boolean, tableforest boolean, targetns text)
此外,还可以使用以下函数,为整个模式或整个当前数据库生成类似的映射:
schema_to_xml(schema name, nulls boolean, tableforest boolean, targetns text) schema_to_xmlschema(schema name, nulls boolean, tableforest boolean, targetns text) schema_to_xml_and_xmlschema(schema name, nulls boolean, tableforest boolean, targetns text) database_to_xml(nulls boolean, tableforest boolean, targetns text) database_to_xmlschema(nulls boolean, tableforest boolean, targetns text) database_to_xml_and_xmlschema(nulls boolean, tableforest boolean, targetns text)
注意,这些函数可能生成大量数据,需要在内存中构建。请求大型模式或数据库的内容映射时,可以考虑分别映射各个表,甚至通过游标来完成。
一个模式内容映射的结果看起来像这样:
<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. 转换 SQL/XML 输出到 HTML 的 XSLT 样式表
<?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>
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。