ISO/IEC 9075-14 (SQL/XML) 中与 XML 相关的规范的重要修改已在 SQL:2006 中引入。PostgreSQL 对 XML 数据类型和相关函数的具体实施在很大程度上遵循早期的 2003 版本,但也借鉴了一些较新的版本。具体来说
当前的标准提供了一个 XML 数据类型系列,用于以非类型化或 XML 模式类型化的变体来保存““文档””或““内容””,以及一个类型 XML(SEQUENCE)
来保存任意片段的 XML 内容,PostgreSQL 提供单个 xml
类型,它可以保存““文档””或““内容””。没有标准的““序列””类型的等效项。
PostgreSQL 提供了 SQL:2006 中引入的两个函数,但使用 XPath 1.0 语言的变体,而不是标准中为它们指定的 XML 查询。
PostgreSQL 不支持 RETURNING CONTENT
或 RETURNING SEQUENCE
子句,规范中定义为具有这些子句的函数隐式返回内容。
本部分介绍可能遇到的部分产生的差异。
PostgreSQL 特定的函数 xpath()
和 xpath_exists()
使用 XPath 语言查询 XML 文档。PostgreSQL 还提供了标准函数 XMLEXISTS
和 XMLTABLE
的仅 XPath 变体,这些函数正式使用 XQuery 语言。对于所有这些函数,PostgreSQL 依赖于仅提供 XPath 1.0 的 libxml2 库。
XQuery 语言与 XPath 2.0 版本和更高版本之间有很强的联系:任何在两者中语法有效并成功执行的表达式都会产生相同的结果(对于包含数字字符引用或预定义实体引用的表达式,有一个小例外,XQuery 会将它们替换为相应字符,而 XPath 会保留它们)。但这些语言与 XPath 1.0 之间没有这种联系;它是一种较早的语言,并且在许多方面有所不同。
需要记住两类限制:SQL 标准中指定的函数从 XQuery 限制到 XPath,以及对标准和 PostgreSQL 特定函数的 XPath 限制为 1.0 版本。
XQuery 的功能超出 XPath 的功能,包括
除了所有可能的 XPath 值之外,XQuery 表达式还可以构造和返回新的 XML 节点。XPath 可以创建和返回原子类型(数字、字符串等)的值,但只能返回已存在于作为输入提供给表达式的文档中的 XML 节点。
对于迭代、排序和分组,XQuery 具有控制结构。
XQuery 允许声明和使用局部函数。
较新的 XPath 版本开始提供与这些功能重叠的能力(例如函数式样 for-each
和 sort
、匿名函数,以及 parse-xml
以从字符串创建节点),但此类功能直到 XPath 3.0 之前才可用。
对于熟悉 XQuery 和 XPath 2.0 或更高级别的人,XPath 1.0 呈现出许多需要解决的不同之处
XQuery/XPath 表达式的基本类型为 sequence
,它可以包含 XML 节点、原子值或两者,但在 XPath 1.0 中并不存在。1.0 表达式只能生成一个节点集(包含零个或多个 XML 节点)或一个单个原子值。
不同于可以按任意所需顺序包含任何所需项的 XQuery/XPath sequence,XPath 1.0 节点集没有固定顺序,并且如同任何集合一样,不允许同一项出现多次。
libxml2 库似乎总是按输入文档中节点的相对顺序将节点集返回给 PostgreSQL。其文档中没有对这种行为进行保证,XPath 1.0 表达式无法对其进行控制。
虽然 XQuery/XPath 提供了 XML Schema 中定义的所有类型及其类型上的多个操作符和函数,但 XPath 1.0 只有节点集和三个原子类型 boolean
、double
和 string
。
XPath 1.0 没有条件操作符。XQuery/XPath 表达式如 if ( hat ) then hat/@size else no hat
在 XPath 1.0 中没有等效项。
XPath 1.0 对字符串没有排序比较操作符。"cat" < dog
和 "cat" > dog
都为 false,因为每个都属于两个 NaN
の数值比较。相比之下,=
和 !=
将字符串作为字符串进行比较。
XPath 1.0 模糊了 XQuery/XPath 定义的值比较 和 通用比较之间的区别。sale/@hatsize = 7
和 sale/@customer = alice
都是存在量化比较,当 sale 中存在一个给定属性值的sale
时,为 true,但 sale/@taxable = false()
是对整个节点集的有效布尔值进行的值比较。只有当没有任何 sale
具有 taxable
属性时,才为 true。
在 XQuery/XPath 数据模型中,文档节点 可以具有文档形式(即一个顶级元素,在它之外只有注释和处理指令)或内容形式(这些约束被放宽)。它在 XPath 1.0 中的等效项 根节点 只能采用文档形式。这是 xml
值作为上下文项传递给任何 PostgreSQL 基于 XPath 的函数时必须采用文档形式的原因之一。
此处突出显示的差异并非全部。在 XQuery 以及 2.0 及更高版本的 XPath 中,有 XPath 1.0 兼容模式,而 W3C 中列出的函数库更改和语言更改在这模式中应用的技术提供了一个更完整的(但仍不详尽的)差异说明。兼容模式不能使新语言与 XPath 1.0 完全相等。
在 SQL:2006 及更高版本中,标准 SQL 数据类型与 XML 架构类型之间的双向转换都得到了明确指定。但规则是使用 XQuery/XPath 的类型和语义来表达的,并且不适用于 XPath 1.0 不同的数据模型。
在 PostgreSQL 将 SQL 数据值映射到 XML(如 xmlelement
中)或 XML 映射到 SQL(如 xmltable
的输出列中)时,除了特别处理的少数情况外,PostgreSQL 只是简单地假设 XML 数据类型的 XPath 1.0 字符串形式将作为 SQL 数据类型的文本输入形式有效,反之亦然。这条规则具有简单性的优点,同时为许多数据类型产生了类似于标准中指定的映射结果。
当需要与其他系统进行互操作时,对于某些数据类型,可能需要显式使用数据类型格式化函数(如 第 9.8 节 中的那些)来生成标准映射。
本节涉及 libxml2 库中并不固有的限制,而是适用于 PostgreSQL 中的当前实现。
BY VALUE
传递机制 #SQL 标准定义了当 XML 参数从 SQL 传递给 XML 函数或接收结果时应用的两个传递机制:BY REF
(其中特定的 XML 值保留其节点标识),以及 BY VALUE
(其中 XML 的内容会被传递,但节点标识不会保留)。可以在参数列表前指定一个机制,作为所有参数的默认机制,也可以在任何参数后指定,以覆盖默认设置。
为了说明差异,如果 x
是一个 XML 值,则在 SQL:2006 环境中,以下两个查询将分别产生 true 和 false
SELECT XMLQUERY('$a is $b' PASSING BY REFx
AS a,x
AS b NULL ON EMPTY); SELECT XMLQUERY('$a is $b' PASSING BY VALUEx
AS a,x
AS b NULL ON EMPTY);
PostgreSQL 会接受 BY VALUE
或 BY REF
根据 XMLEXISTS
或 XMLTABLE
构造,但会忽略它们。xml
数据类型持有字符窜序列化的表示,因此没有节点身份来保存,并且传递实际上总是 BY VALUE
。
基于 XPath 的函数支持传递一个参数用作 XPath 表达式的上下文项目,但不支持传递其他值用作表达式可用的带命名参数。
XML(SEQUENCE)
类型 #The PostgreSQL xml
数据类型只能以 DOCUMENT
或 CONTENT
形式持有值。XQuery/XPath 表达式上下文项目必须是单个 XML 节点或原子值,但 XPath 1.0 进一步将其限制为只能是 XML 节点,并且没有允许 CONTENT
的节点类型。结果便是合法的 DOCUMENT
是 PostgreSQL 可作为 XPath 上下文项目提供的 XML 值的唯一形式。