XML 类型

本文介绍了XML类型的定义及相关语法。

xml数据类型可以被用来存储 XML 数据。它比直接在一个text域中存储 XML 数据的优势在于,它会检查输入值的结构是不是良好,并且有支持函数用于在其上执行类型安全的操作。使用这种数据类型要求在安装时用configure --with-libxml选项编译。

xml类型可以存储格式良好的遵循 XML 标准定义的“文档”,以及“内容”片段,它是通过引用更宽泛的“document node” XQuery 和 XPath 数据模型来定义的。 大致上说,这意味着内容片段中可以有多于一个的顶层元素或字符节点。 表达式xmlvalue`` IS DOCUMENT可以被用来评估一个特定的xml值是一个完整文档或者仅仅是一个文档片段。

创建XML值

要从字符数据中生成一个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

也可以被使用。

即便输入值指定了一个文档类型声明(DTD),xml类型也不根据 DTD 来验证输入值。目前也没有内建的支持用于根据其他 XML 模式语言(如 XML 模式)来进行验证。

作为一个逆操作,从xml产生一个字符串可以使用函数xmlserialize

    XMLSERIALIZE ( { DOCUMENT | CONTENT } value AS type )

type可以是 charactercharacter varyingtext(或者其中之一的一个别名)。再次地,根据 SQL 标准,这也是在xml类型和字符类型间做转换的唯一方法,但是 PostgreSQL 也允许你简单地造型这些值。

当一个字符串不是使用XMLPARSE造型成xml或者不是使用XMLSERIALIZExml造型得到,对于DOCUMENTCONTENT两者的选择是根据“XML option” 会话配置参数决定的,它可以使用标准命令来设置:

    SET XML OPTION { DOCUMENT | CONTENT };

或者是更具有 PostgreSQL 风格的语法

    SET xmloption TO { DOCUMENT | CONTENT };

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

编码处理

在客户端、服务器以及其中流过的 XML 数据上处理多字符编码时必须要注意。在使用文本模式向服务器传递查询以及向客户端传递查询结果(在普通模式)时,PostgreSQL 将所有在客户端和服务器之间传递的字符数据转换为目标端的字符编码。这也包括了表示 XML 值的串,正如上面的例子所述。这也通常意味着由于字符数据会在客户端和服务器之间传递时被转换成其他编码,包含在 XML 数据中的编码声明可能是无效的,因为内嵌的编码声明没有被改变。为了处理这种行为,包含在表示xml类型输入的字符串中包含的编码声明会被忽略,并且其内容被假定为当前服务器的编码。接着,为了正确处理,XML 数据的字符串必须以当前客户端编码从客户端发出。客户端负责在把文档发送给服务器之前将它们转换为当前客户端编码,或者适当地调整客户端编码。在输出时,xml类型的值将不会有一个编码声明,并且客户端将会假设所有数据都是当前客户端编码。

在使用二进制模式传送查询参数给服务器以及传回查询结果给客户端时,不会执行编码转换,因此情况就有所不同。在这种情况下,XML 数据中的编码声明将被注意到,并且如果缺少编码声明时该数据会被假定为 UTF-8(由于 XML 标准的要求,注意 PostgreSQL 不支持 UTF-16)。在输出时,数据将会有一个编码声明来指定客户端编码,除非客户端编码为 UTF-8(这种情况下编码声明会被忽略)。

不用说,在 PostgreSQL 中处理 XML 数据产生错误的可能性更小,并且在 XML 数据编码、客户端编码和服务器编码三者相同时效率更高。因为 XML 数据在内部是以 UTF-8 处理的,如果服务器编码也是 UTF-8 时,计算效率将会最高。

重要

当服务器编码不是 UTF-8 时,某些 XML 相关的函数可能在非 ASCII 数据上完全无法工作。尤其在xmltable()xpath()上,这是一个已知的问题。

访问XML值

xml数据类型有些不同寻常,因为它不提供任何比较操作符。这是因为对于 XML 数据不存在良定义的和通用的比较算法。这种状况造成的后果就是,你无法通过比较一个xml和一个搜索值来检索行。XML 值因此通常应该伴随着一个独立键值域,如一个 ID。另一种比较 XML 值的方案是将它们先转换为字符串,但注意字符串比较对于 XML 比较方法没有什么帮助。

由于没有可以用于xml数据类型的比较操作符,因此无法直接在这种类型上创建索引。如果需要在 XML 中快速的搜索,可能的解决方案包括将表达式造型为一个字符串类型然后索引之,或者在一个 XPath 表达式上索引。当然,实际的查询必须被调整为使用被索引的表达式。

PostgreSQL 中的文本搜索功能也可以被用来加速 XML 数据的全文搜索。但是,所需的预处理支持目前在 PostgreSQL 发布中还不可用。