可以使用 xml
数据类型来存储 XML 数据。它相对于在 text
字段中存储 XML 数据的优势在于,它会检查输入值的规范性,并且有一些支持函数能够在 XML 上执行类型安全的操作;参见 第 9.15 节。使用此数据类型需要使用 configure --with-libxml
编译安装。
xml
类型可以存储符合 XML 标准规定的规范 “文档”,以及通过引用更宽容的 XQuery 和 XPath 数据模型的 “文档节点” 进行定义的 “内容” 片段。大致上来说,这意味着内容片段可以具有多个顶级元素或字符节点。表达式
可用于评估特定的 xmlvalue
IS DOCUMENTxml
值是完整文档还是仅仅是内容片段。
xml
数据类型的限制和兼容性说明可在 第 D.3 节 中找到。
要根据字符数据生成类型为 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 Schema)进行验证。
反向操作(从 xml
生成字符串值)使用函数 xmlserialize
:
XMLSERIALIZE ( { DOCUMENT | CONTENT }value
AStype
[ [ NO ] INDENT ] )
type
可以是 character
、character varying
或 text
(或其中一个的别名)。同样,根据 SQL 标准,这是在类型 xml
与字符类型之间进行转换的唯一方法,但 PostgreSQL 也允许直接对值进行数据类型转换。
INDENT
选项会导致以漂亮格式打印结果,而 NO INDENT
(这是默认项)只会发出原始的输入字符串。数据类型转换为字符类型也会生成原始字符串。
当字符字符串值被强制转换为 xml
类型或从中转换而没有分别经过 XMLPARSE
或 XMLSERIALIZE
时,DOCUMENT
和 CONTENT
的选择取决于 “XML 选项” 会话配置参数,可以使用标准命令将其设置
SET XML OPTION { DOCUMENT | CONTENT };
或更类似于 PostgreSQL 的语法
SET xmloption TO { DOCUMENT | CONTENT };
默认值为 CONTENT
,因此允许使用所有形式的 XML 数据。
在处理客户端、服务器以及通过它们传递的 XML 数据中的多个字符编码时,必须小心。在使用文本模式将查询传递给服务器,并将查询结果传递给客户端(这是正常模式)时,PostgreSQL 会将客户端和服务器之间传递的所有字符数据以及反之转换为相应结尾的字符编码;请参阅 第 23.3 节。这包括 XML 值的字符串表示,例如在上面的示例中。这通常意味着包含在 XML 数据中的编码声明可能会在字符数据在客户端和服务器之间传输期间转换为其他编码时变为无效,因为不会更改嵌入式编码声明。为了应对这种行为,包含在呈现为 xml
类型的输入中的字符字符串中的编码声明 已被忽略,并且内容被视为采用当前服务器编码。因此,为了正确处理,XML 数据的字符字符串必须从客户端以当前客户端编码发送。客户端负责在将 XML 文档发送到服务器之前将其转换为当前客户端编码,或适当调整客户端编码。在输出时,xml
类型的值不会具有编码声明,客户端应假定所有数据都采用当前客户端编码。
在使用二进制模式将查询参数传递到服务器并将查询结果返回给客户端时,不会执行任何编码转换,因此情况有所不同。在这种情况下,将观察 XML 数据中的编码声明,并且如果不存在该声明,则数据将被视为 UTF-8(这是 XML 标准的要求;注意 PostgreSQL 不支持 UTF-16)。在输出时,数据将具有指定客户端编码的编码声明,除非客户端编码是 UTF-8,在这种情况下它将被省略。
不用说,如果 XML 数据编码、客户端编码和服务器编码相同,使用 PostgreSQL 来处理 XML 数据将减少出错的风险并提高效率。由于 XML 数据在内部以 UTF-8 处理,因此如果服务器编码也是 UTF-8,计算将最有效率。
当服务器编码不是 UTF-8 时,一些与 XML 相关的函数可能完全无法处理非 ASCII 数据。我们已知 xmltable()
和 xpath()
存在这个问题。
xml
数据类型比较特殊,因为它不提供任何比较运算符。这是因为没有针对 XML 数据的明确定义且对所有人有用的比较算法。此特性导致的一个后果是,您无法通过将 xml
列与搜索值进行比较来检索行。因此,XML 值通常应带有单独的键字段,例如 ID。比较 XML 值的另一种解决方案是先将它们转换为字符串,但请注意字符串比较与实用的 XML 比较方法几乎没有关系。
由于 xml
数据类型没有比较运算符,因此无法直接针对此类型的一列创建索引。如果您想要在 XML 数据中进行快速搜索,可能的解决方法包括将表达式转换为字符串类型并对其编制索引,或对 XPath 表达式编制索引。当然,实际查询必须调整为按编制索引的表达式进行搜索。
PostgreSQL 中的文本搜索功能还可以用来加速对 XML 数据的全文搜索。但现阶段,PostgreSQL 发行版中尚未提供必要的预处理支持。