XML 支持

来自 PostgreSQL wiki
跳转到导航跳转到搜索
该项目已基本完成。要了解当前问题,请参阅 XML Todo

开始使用 PostgreSQL 的 XML 支持时,您应首先在手册中阅读 PostgreSQL XML 数据类型PostgreSQL XML 函数 文档。本页讨论该即将完成的大量工作的规划,以下内容因而过时。

过时内容 - XML 支持规划

SQL 数据库中的 XML 支持可以包含很多不同的意思,但通常指以下三种之一

  • XML 数据类型和支持函数
  • XML 导出格式
  • 将 XML 文档映射到 SQL 数据库

前两部分的大多数接口由 ISO/IEC 9075-14(“与 XML 相关的规范” - SQL/XML)编制。自 2006-06-12 起,我们现在可使用 ISO/IEC 9075-14:2006。(这实际上可能不是“SQL:2006”,因为它是在那时发布的唯一 SQL 部分。)IBM DB/2、Microsoft SQL Server、OpenLink Virtuoso、Oracle 和其他一些系统已实施了这些接口,因此遵循该路径有一定的道理。您可以在 http://www.sqlx.org/ 上找到更多有关此标准的信息,尽管已经过时了。

请注意,2006 标准是对 2003 版本(SQL/XML 的第一个版本)的相当大的提升,因此,为了保持我们的理智,最好首先瞄准 2003 版本。

XML 数据类型和支持函数

XML 数据类型可能是“XML 支持”中最有意思的一项。以下是一些有关其工作原理和状态报告的详细信息。

XML 数据类型

实际操作中的 XML 数据类型毫不奇怪地看起来是这样的

CREATE TABLE test (
    ...,
    data xml,
    ...
);

与任何数据类型一样,它具有输入检查和支持功能,使其变得有用。

严格来说,xml类型不接受字符串文本作为输入。将文本字符串转换为 XML 数据并返回的方法是

XMLPARSE ( DOCUMENT|CONTENT value ) --> xml
XMLSERIALIZE ( DOCUMENT|CONTENT xmlvalue AS varchar ) --> varchar

这些用作 PostgreSQL 输入/输出函数,周围具有某些语法包装器以支持标准语法。

一个xmldatum 可包含两种类型的值:文档或片段。文档包含报头、根元素和使 XML 文档成型的所有其他内容。片段仅看起来像 XML 语法,但并非(不一定)一个完整的文档。这就是某些语法部分引用DOCUMENTCONTENT(与片段相同,命名不一致)。

XML 支持函数

SQL 为以下函数式表达式指定了xml数据类型

  • XMLCOMMENT
  • XMLCONCAT
  • XMLELEMENT
  • XMLFOREST
  • XMLPI
  • XMLROOT
  • XMLAGG
  • IS DOCUMENT, IS NOT DOCUMENT

实际上,这些是经过美化的字符串连接函数,但它们执行所有正确的转义和嵌套,并添加了一些便利功能,用于将 SQL 数据处理成 XML 数据。以下是一些示例

XMLROOT (
  XMLELEMENT (
    NAME gazonk,
    XMLATTRIBUTES (
      ’val’ AS name,
      1 + 1 AS num
    ),
    XMLELEMENT (
      NAME qux,
      ’foo’
    )
  ),
  VERSION ’1.0’,
  STANDALONE YES
)

这生成以下 XML 文档

<?xml version=’1.0’ standalone=’yes’ ?>
<gazonk name=’val’ num=’2’>
  <qux>foo</qux>
</gazonk>

这展示了 SQL 表达式如何像 XML 元素一样嵌套。

这是一个 XML “林”的示例

SELECT xmlforest (
  "FirstName" as "FName", "LastName" as "LName",
  ’string’ as "str", "Title", "Region" )
FROM "Demo"."demo"."Employees";

如果有部分 employees 表中的数据,可能会导致

<FName>Nancy</FName>
<LName>Davolio</LName>
<str>string</str>
<Title>Sales Representative</Title>
<Region>WA</Region>
...
<FName>Anne</FName>
<LName>Dodsworth</LName>
<str>string</str>
<Title>Sales Representative</Title>

每个这些员工记录都是一个 SQL datum。

由于XMLFOREST的结果是一个xmldatum,你可以将它与XMLELEMENT和其他表达式一起嵌套,以进一步修饰结果。

这是一个使用聚合函数的示例XMLAGG:

SELECT xmlelement (’Emp’,
   xmlattributes (’Sales Representative’ as "Title"),
   xmlagg (xmlelement (’Name’, "FirstName", ’ ’,
                        "LastName")))
   FROM "Demo"."demo"."Employees"
   WHERE "Title" = ’Sales Representative’;

这可能会导致

<Emp Title="Sales Representative">
  <Name>Nancy Davolio</Name>
  <Name>Janet Leverling</Name>
  <Name>Margaret Peacock</Name>
  <Name>Michael Suyama</Name>
  <Name>Robert King</Name>
  <Name>Anne Dodsworth</Name>
</Emp>

这里,结果是一个 SQL datum。

SQL/XML 2006

SQL/XML 2006 添加了更多

  • 有一个具体 XML 数据类型,不仅允许文档与片段,还允许文档验证
    • XML
    • XML(DOCUMENT)
    • XML(CONTENT)
    • XML(SEQUENCE)
    • XML(DOCUMENT(ANY))
    • XML(DOCUMENT(UNTYPED))
    • XML(DOCUMENT(XMLSCHEMA ’http://...’))
  • 添加了一些支持函数/表达式
    • XMLDOCUMENT
    • XMLTEXT
    • XMLVALIDATE
    • IS CONTENT
    • IS VALID
  • 在所有意想不到的语法元素中都添加了更多与 XML 相关的选项。这不太好看。
  • 添加了 XQuery 支持。

状态

帕维尔·斯蒂胡勒提供的一份支持 SQL/XML 2003 函数的补丁包已可用一段时间。此补丁包不包括 XML 数据类型;它操作存储在文本字段中的 XML 数据。

Nikolay Samokhvalov 的 2006 年 Google 夏日编程代码项目,由 Peter Eisentraut 指导,旨在提供对 SQL/XML 2003 的完整支持。此工作整合并改进了 Pavel Stehule 的补丁。夏日编程代码已结束,一个相当完整的实现已经产生。我们希望尽早将其集成到 8.3 中。

实现问题

如提案中所述,实现使用了著名的 libxml,它获得了 LGPL 授权,因此不会给 PostgreSQL 造成问题。已在某一时刻遇到的某些实现问题(现在可能已经得到解决)是

  • 编码处理很奇怪。XML 文档携带有它们自己的编码信息。如果您(比如说)拥有一份自认为是以 UTF-8 编码的文档,并且在 PostgreSQL 客户端/服务器连接(该连接将客户端侧的 UTF-8 转换为服务器上其他内容)中发送该文档,服务器中的 XML 解析器将抱怨。其他组合中也存在类似的情况。目前尚不清楚如何解决此问题。
  • libxml 中的内存管理需要仔细处理。libxml 提供了更换挂钩malloc()free(),这很好,但它似乎想怎样就怎样调用 free 挂钩,如果以其他方式 PostgreSQL 内存管理器已经释放了内存,这可不妙。此问题在错误恢复期间尤为严重。这个问题肯定可以解决,但需要进行验证。
  • 此功能在多大程度上应该是强制性的还是可选的?某些构建时选项没问题,但无法轻松使用 ifdef 忽略特殊语法支持。我们需要针对这些情况提供一些可靠的恢复能力。

未来项目

一旦xml类型可用,contrib/xml/中的功能应调整为这些新功能。

很多人提交了夏日编程代码申请,准备实现 CTree 索引。关于这一点的信息不多,但如果您在 Google Scholar 上查看,会发现它是一种适用于 XML 数据的新型索引类型(并不稀奇)。在 XML 类型真正存在之前提出为此工作可能为时过早,但一旦完成,CTree 支持可能是一个有趣的项目。

SQL/XML 2006 要求完全集成 XQuery。Sleepycat 有一个 XQuery 库,我们可以使用该库。(我上次查看时,构建库很麻烦,部署也并不广泛。不过,Sleepycat 的人非常乐意满足 PostgreSQL 的兴趣。不过,那是在他们被收购之前。)但是,重复使用 PostgreSQL 现有的查询计划和执行设施,并将 XQuery 视为 SQL 的并行备选方案似乎更有意义。这是其他一些供应商处理此问题的方法。但是,对于 PostgreSQL 来说,这将是一个大的不敢说范式的转变。

XML 导出格式

每个人都可以创建自己的关系数据 XML 导出格式,并且许多人过去都曾在 PostgreSQL 邮件列表中提出了自己的发明。为了确定一种格式,SQL 标准包含对其进行规范说明。

具体而言,针对以下内容提供规范说明:

  • 将 SQL 架构映射到 XML 模式
  • 将数据库内容映射到 XML 文档(遵循上述 XML 模式文档)

XML 导出格式可能对以下内容有用:

使用 XSLT 进行后处理
轻松、自动地将 SQL 数据转换为 XHTML 或 DocBook。
pg_dump
作为通用备份格式?
psql
替换或增强现有的 HTML 支持?

转义

SQL 指定的 XML 导出格式胜过临时定义格式之处在于其完善的转义机制,如下所示

SQL <标识符> 完全转义的 XML 名称 部分转义的 XML 名称
员工 EMPLOYEE EMPLOYEE
"雇员" 员工 员工
"入职日期" hire_x0020_date hire_x0020_date
"补偿计划" comp_x005F_plan comp_x005F_plan
"部门:编号" dept_x003A_id dept:id
xmlcol _xFFFF_xmlcol xmlcol

根据实际情况,使用两种不同的转义形式。

模式映射

例如,以下是表定义在 XML 模式中的方式。

CREATE TABLE test (a int PRIMARY KEY, b varchar(200));
<xsd:complexType name="RowType.catalog.schema.test">
  <xsd:sequence>
    <xsd:element name="a" type="INTEGER"></xsd:element>
    <xsd:element name="b" type="VARCHAR_200_200"
        minOccurs="0"></xsd:element>
  </xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TableType.catalog.schema.test">
  <xsd:sequence>
    <xsd:element name="row"
        type="RowType.catalog.schema.test"
        minOccurs="0"
        maxOccurs="unbounded" />
  </xsd:sequence>
</xsd:complexType>

数据映射

以下是导出只有一个表的通用数据库的方式

<catalogname>
  <schemaname>
    <tablename>
      <row>
        <colname1>value</colname1>
        <colname2 xsi:nil=’true’/>
        ...
      </row>
      ...
    </tablename>
    ...
  </schemaname>
  ...
</catalogname>

元素名称实际上将被相关对象的实际名称替换(因此需要转义)。以上示例中唯一的元素名称文字是,因为行没有名称。

对于 NULL 处理有多种选择。以上示例使用特殊属性对其进行处理。另一种选择是省略元素。

状态

Peter Eisentraut 为 XML 导出和导入提供了可用原型。导出几乎只是提取目录信息并将其打印出来的勤奋工作。在这个原型中,导入实际上是一个表函数。总的来说,首先拥有 XML 数据类型很有好处,然后才能进一步进行,这样以后不必更改界面。

一个问题是将它放在哪里。

pg_dump?
这将符合“导出”主题,但它可能会限制该功能的灵活性。
psql?
许多之前的建议将工作放在 psql 中,但这似乎不太妥当。
用户定义函数?
这听起来不错,并且可以很好地与 XML 数据类型支持集成。但我们可能需要一个“流”变体来导出大型表。

将 XML 文档映射到 SQL 数据库

将 XML 文档映射到 SQL 数据库包括解析 XML 文档的层次结构,并使用各自的数据创建相应的互连 SQL 表。SQL 未对此进行规范说明,但数据库理论家肯定已经弄清楚了这一点。

但实际上,这不是特定于 PostgreSQL 的问题,所以解决它并不是真正我们的工作。例如,Perl 模块 DBIx-XML-DataLoader 实现了该功能。

链接