Postgresql 中文操作指南

8.13. XML Type #

xml 的数据类型可用于存储 XML 数据。它优于在 text 字段中存储 XML 数据,因为它会检查输入值是否格式正确,并且有一些支持函数可以对其执行类型安全操作;请参见 Section 9.15。使用此数据类型要求已用 configure --with-libxml 构建安装程序。

xml 类型可存储 XML 标准定义的格式良好的“文档”,以及“内容”片段,即通过引用 XQuery 和 XPath 数据模型的更宽松规范来定义的内容片段。从大致上说,这意味着内容片段可以有多个顶级元素或字符节点。表达式 _xmlvalue IS DOCUMENT_ 可用于评估特定 xml 值是完整文档还是仅是内容片段。

xml 的数据类型的限制和兼容性注释可以在 Section D.3 中找到。

8.13.1. Creating XML Values #

要通过字符数据生成 xml 类型的值,请使用以下函数 xmlparse

XMLPARSE ( { DOCUMENT | CONTENT } value)

示例:

XMLPARSE (DOCUMENT '<?xml version="1.0"?><book><title>Manual</title><chapter>...</chapter></book>')
XMLPARSE (CONTENT 'abc<foo>bar</foo><bar>foo</bar>')

虽然这是根据 SQL 标准将字符串转换为 XML 值的唯一方法,但 PostgreSQL 特有的语法为:

xml '<foo>bar</foo>'
'<foo>bar</foo>'::xml

也可以使用。

xml 类型不会针对文档类型声明(DTD)验证输入值,即使输入值指定 DTD 也是如此。目前也没有针对 XML 模式这类其他 XML 模式语言进行验证的内置支持。

反向运算(即通过 xml 制作字符字符串值)使用了 xmlserialize 函数:

XMLSERIALIZE ( { DOCUMENT | CONTENT } value AS type [ [ NO ] INDENT ] )

type 可以是 charactercharacter varyingtext(或其中一个的别名)。同样,根据 SQL 标准,这是 xml 类型和字符类型间唯一转换方式,但 PostgreSQL 允许您简单地转换该值。

INDENT 选项会将结果作为漂亮格式输出,而 NO INDENT(这是默认选择)只会发出原始输入字符串。同样,转换到字符类型会产生原始字符串。

当将字符字符串值转换为或转换自 xml 类型且没有分别经过 XMLPARSEXMLSERIALIZE 时,DOCUMENTCONTENT 的选择将由“XML 选项”会话配置参数决定,该参数可使用标准命令设置:

SET XML OPTION { DOCUMENT | CONTENT };

或更类似 PostgreSQL 的语法

SET xmloption TO { DOCUMENT | CONTENT };

默认值为 CONTENT,因此允许所有形式的 XML 数据。

8.13.2. Encoding Handling #

在处理客户端、服务器和通过它们的 XML 数据上的多个字符编码时,必须小心。使用文本模式将查询传递给服务器并将查询结果传递给客户端(这是正常模式)时,PostgreSQL 将客户端和服务器之间传递的所有字符数据以及反之亦然都转换为各个端的字符编码;请参见 Section 24.3。这包括 XML 值的字符串表示,例如以上示例中的值。通常,这意味着 XML 数据中包含的编码声明可能会在字符数据在客户端和服务器之间传输时转换为其他编码而变得无效,因为嵌入的编码声明不会改变。为了应对此行为,xml 所输入的字符中包含的编码声明的类型被 ignored,并且内容被假定为当前服务器编码。因此,为了正确处理,XML 数据的字符必须从客户端以当前客户端编码发送。客户端负责在将文档发送到服务器之前将其转换为当前客户端编码,或适当地调整客户端编码。在输出时,xml 类型的值不会有编码声明,并且客户端应假设所有数据都在当前客户端编码中。

当使用二进制模式将查询参数传递到服务器并将查询结果传回客户端时,不会执行编码转换,因此情况不同。在这种情况下,将会识别 XML 数据中的编码声明,如果没有,则将假设数据采用 UTF-8 格式(XML 标准要求如此;请注意,PostgreSQL 不支持 UTF-16)。在输出中,数据将具有指定客户端编码的编码声明,但如果客户端编码是 UTF-8,则将被忽略。

毋庸置疑,如果 XML 数据编码、客户端编码和服务器编码相同,那么在 PostgreSQL 中处理 XML 数据出错的可能性更小,而且效率更高。由于 XML 数据在内部以 UTF-8 处理,因此当服务器编码也是 UTF-8 时,计算的效率最高。

Caution

某些与 XML 相关的函数在服务器编码不是 UTF-8 时可能完全无法处理非 ASCII 数据。众所周知,xmltable()xpath() 特别存在此问题。

8.13.3. Accessing XML Values #

xml 数据类型很特别,因为它不提供任何比较运算符。这是因为对于 XML 数据没有定义清晰且普遍有用的比较算法。这造成的一个后果是,您无法通过将 xml 列与搜索值进行比较来检索行。因此,XML 值通常应包含单独的主键字段,例如 ID。比较 XML 值的另一种解决方案是先将它们转换为字符字符串,但请注意,字符字符串比较与有用的 XML 比较方法几乎没有关系。

由于 xml 数据类型没有比较运算符,因此无法直接在该类型的一列上创建索引。如果需要在 XML 数据中进行快速搜索,可能的解决方法包括将表达式转换为字符字符串类型并对其编制索引,或索引 XPath 表达式。当然,实际查询必须调整为按索引表达式进行搜索。

PostgreSQL 中的文本搜索功能也可以用于加速 XML 数据的全文档搜索。但相关的前置处理支持尚不可用在 PostgreSQL 发行版中。