Postgresql 中文操作指南
D.3. XML Limits and Conformance to SQL/XML #
SQL:2006 引入了对 ISO/IEC 9075-14 (SQL/XML) 中的 XML 相关规范的重大修订。PostgreSQL 对 XML 数据类型的实现以及相关的函数主要遵循早期的 2003 年版本,并从较晚的版本中借用了部分内容。特别是:
此部分介绍部分可能会遇到的差异结果。
D.3.1. Queries Are Restricted to XPath 1.0 #
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 之间没有这种关联性;XPath 1.0 是一种较早的语言,在许多方面都不同。
有两类限制需要记住:针对 SQL 标准中指定函数将 XQuery 限制为 XPath,以及针对标准函数和 PostgreSQL 专有函数将 XPath 限制为 1.0 版。
D.3.1.1. Restriction of XQuery to XPath #
XQuery 优于 XPath 的特性包括:
最近的 XPath 版本开始提供与这些功能重叠的能力(例如功能风格 for-each 和 sort、匿名函数,以及 parse-xml 从字符串中创建节点),但此类功能在 XPath 3.0 之前不可用。
D.3.1.2. Restriction of XPath to 1.0 #
对于熟悉 XQuery 和 XPath 2.0 或更高版本的开发人员,XPath 1.0 提出了许多差异需要解决:
Note
libxml2 库似乎总是将节点集返回给 PostgreSQL,且其成员与输入文档中的相对顺序相同。它的文档没有包含此行为,并且 XPath 1.0 表达式无法控制它。
此处突出显示的区别并不是全部。在 XQuery 和 XPath 的 2.0 及更高版本中,存在 XPath 1.0 兼容性模式,W3C 中列出的 function library changes 和 language changes 在该模式中应用,提供了更完整(但仍然不详尽)的区别说明。兼容性模式无法使更高版本的语言与 XPath 1.0 完全等效。
D.3.1.3. Mappings between SQL and XML Data Types and Values #
在 SQL:2006 及更高版本中,标准 SQL 数据类型与 XML Schema 类型之间的转换的两个方向都得到了精确指定。但是,这些规则是用 XQuery/XPath 的类型和语义来表达的,并且不直接适用于 XPath 1.0 的不同数据模型。
当 PostgreSQL 将 SQL 数据值映射到 XML(如 xmlelement 所示)时,或将 XML 映射到 SQL(如 xmltable 的输出列中所述),除了经过特殊处理的少数情况外,PostgreSQL 只是简单地假设 XML 数据类型的 XPath 1.0 字符串形式将作为 SQL 数据类型的文本输入形式有效,反之亦然。此规则具有简单性的优点,同时对许多数据类型产生类似于标准中指定映射的结果。
在与其他系统互操作是个问题的地方,对于某些数据类型,可能需要显式使用数据类型格式化函数(例如 Section 9.8 中的那些函数)来生成标准映射。
D.3.2. Incidental Limits of the Implementation #
本部分涉及的限制不是 libxml2 库固有的,而是适用于 PostgreSQL 中的当前实现。
D.3.2.1. Only BY VALUE Passing Mechanism Is Supported #
SQL 标准定义了两个 passing mechanisms,当从 SQL 传递 XML 参数到 XML 函数或接收结果时适用:BY REF,其中特定 XML 值保留其节点标识;以及 BY VALUE,其中传递 XML 的内容,但节点标识不会保留。可在参数列表前指定机制,作为所有参数的默认机制,或在任何参数后指定机制,以覆盖默认值。
为了说明差异,如果 x 是一个 XML 值,那么在 SQL:2006 环境中的这两个查询将分别产生真和假:
SELECT XMLQUERY('$a is $b' PASSING BY REF x AS a, x AS b NULL ON EMPTY);
SELECT XMLQUERY('$a is $b' PASSING BY VALUE x AS a, x AS b NULL ON EMPTY);
PostgreSQL 将在 XMLEXISTS 或 XMLTABLE 结构中接受 BY VALUE 或 BY REF,但会忽略它们。xml 数据类型保存序列化字符串表示形式,因此没有节点标识需要保留,并且传递始终有效 BY VALUE。
D.3.2.2. Cannot Pass Named Parameters to Queries #
基于 XPath 的函数支持传递一个参数作为 XPath 表达式的上下文项目,但不支持传递附加值作为命名参数提供给表达式。
D.3.2.3. No XML(SEQUENCE) Type #
PostgreSQL xml 数据类型只能保留 DOCUMENT 或 CONTENT 形式的值。XQuery/XPath 表达式上下文项目必须是单个 XML 节点或原子值,但 XPath 1.0 进一步将其限制为仅是 XML 节点,并且没有允许 CONTENT 的节点类型。结果是,格式良好的 DOCUMENT 是 PostgreSQL 可以作为 XPath 上下文项目提供的 XML 值的唯一形式。