ISO/IEC 9075-14 (SQL/XML) 中与 XML 相关的规范的重大修订是在 SQL:2006 中引入的。PostgreSQL 对 XML 数据类型和相关函数的实现主要遵循早期的 2003 版,并从后来的版本中借鉴了一些内容。特别是
当当前标准提供一系列 XML 数据类型来存储“文档” 或 “内容” 在无类型或 XML Schema 类型变体中,以及类型 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 依赖于 libxml2 库,该库仅提供 XPath 1.0。
XQuery 语言与 XPath 2.0 及更高版本之间存在密切的联系:任何在语法上有效并在两者中成功执行的表达式都会产生相同的结果(对于包含数字字符引用或预定义实体引用的表达式有一个小例外,XQuery 会用相应的字符替换这些引用,而 XPath 会保留它们)。但这些语言与 XPath 1.0 之间没有这种联系;它是一种更早的语言,在许多方面有所不同。
有两个类别的限制需要牢记:从 SQL 标准中指定的函数的 XQuery 到 XPath 的限制,以及从标准和 PostgreSQL 特定函数的 XPath 到 1.0 版本的限制。
XQuery 超出 XPath 的功能包括
XQuery 表达式可以构造并返回新的 XML 节点,以及所有可能的 XPath 值。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 序列不同,XQuery/XPath 序列可以按任何所需的顺序包含任何所需的项目,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"
都为假,因为每个都是两个 NaN
的数值比较。相反,=
和 !=
确实将字符串作为字符串进行比较。
XPath 1.0 模糊了 XQuery/XPath 定义的 值比较 和 一般比较 之间的区别。 sale/@hatsize = 7
和 sale/@customer = "alice"
都是存在量化比较,如果存在任何具有给定属性值的 sale
,则为真,但 sale/@taxable = false()
是对整个节点集的 有效布尔值 的值比较。它仅在根本没有 sale
具有 taxable
属性时才为真。
在 XQuery/XPath 数据模型中,文档节点 可以具有文档形式(即,只有一个顶级元素,在其外部只有注释和处理指令)或内容形式(这些约束放宽)。它在 XPath 1.0 中的等效项 根节点 只能以文档形式存在。这是将 xml
值作为上下文项传递给任何 PostgreSQL 基于 XPath 的函数的原因之一,该值必须以文档形式存在。
这里强调的差异并非全部。在 XQuery 以及 XPath 的 2.0 及更高版本中,存在 XPath 1.0 兼容模式,并且 W3C 的 函数库更改 和 语言更改 的列表在该模式下应用,提供了更完整(但仍然不详尽)的差异说明。兼容模式无法使后来的语言与 XPath 1.0 完全等效。
在 SQL:2006 及更高版本中,标准 SQL 数据类型与 XML Schema 类型之间的双向转换都已精确指定。但是,这些规则是使用 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 标准定义了两种适用于从 SQL 将 XML 参数传递给 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 将在 XMLEXISTS
或 XMLTABLE
结构中接受 BY VALUE
或 BY REF
,但会忽略它们。 xml
数据类型保存字符字符串序列化表示形式,因此没有节点标识需要保留,并且传递始终实际上是 BY VALUE
。
基于 XPath 的函数支持传递一个参数作为 XPath 表达式的上下文项,但不支持传递其他值以作为命名参数供表达式使用。
XML(SEQUENCE)
类型 #PostgreSQL xml
数据类型只能保存以 DOCUMENT
或 CONTENT
形式存在的值。XQuery/XPath 表达式上下文项必须是单个 XML 节点或原子值,但 XPath 1.0 进一步将其限制为仅为 XML 节点,并且没有允许 CONTENT
的节点类型。结果是,格式良好的 DOCUMENT
是 PostgreSQL 可以作为 XPath 上下文项提供的 XML 值的唯一形式。
如果您在文档中发现任何错误,与您对特定功能的体验不符,或者需要进一步澄清,请使用 此表格 报告文档问题。