葡萄牙语::XMLnoPostgreSQL
需要改进内容的文本
PostgreSQL 中的 XML
可以将 XML 文档与关系型数据库(如 PostgreSQL)集成,创建混合数据库。我曾经遇到过纯关系型模型效率极低的情况,并找到了在关系型数据库中使用 XML 文档的解决方案。此外,正在出现使用关系型数据库作为基础的 XML 文档管理应用程序。PostgreSQL 对 XML 的支持通过 contrib/xml 目录中的一个扩展实现。它基于现有的用于操作 XML 和 XPath 查询(一种用于查询 XML 文档的语言)的函数库 libxml。该扩展主要为 PostgreSQL 提供两种功能:
- 根据 DTD 验证 XML 文档(通过 pgxml_parse 函数);
- 对存储的文档进行 XPath 查询(通过 pgxml_xpath 函数)。
当在数据库中使用 XML 文档存储时,这两项功能至关重要。
安装
使用这两个函数的第一步是安装 xml 模块。要编译 xml 模块的源代码,无论使用哪种平台,都需要下载 libxml 的源代码。为此,只需访问网站 ftp://xmlsoft.org/,复制文件(libxml2-2.5.6.tar.gz 或最新版本)并将 include 文件夹中的 .h 文件解压缩到您在 contrib/xml 中创建的名为 libxml 的目录中。
cd diretorio_fontes_postgresql/contrib/xml
gmake
gmake install
注意
需要注意的是,RedHat 的 postgresql-contrib RPM 包没有安装此模块(至少在 RedHat 8 之前是如此)。一些 PostgreSQL 版本在从 FreeBSD 的 ports 安装时已经包含 libxml 文件。安装完模块后,需要执行 pgxml.sql 文件中包含的 SQL 命令,以在您将要使用它们的数据库中创建函数。
用法
使用第一个函数 pgxml_parse,我们可以确保 XML 文档与其定义(DTD)一致,从而可以轻松地对文档进行 XPath 查询,并保持数据库完整性。此函数可以创建一条规则,在插入包含文档的行时验证 XML。以下函数可用于验证 "documentos" 表中包含的文档内容与其在 "formatos" 表中的 DTD。
CREATE OR REPLACE FUNCTION validaXML(int4, int4) RETURNS bool AS
'
SELECT pgxml_parse((SELECT dtd FROM formatos WHERE formatos.codformato = $2) || CONVERT(documentos.conteudo, ''LATIN1'', ''UNICODE''))
FROM documentos WHERE documentos.coddocumento = $1;
'
LANGUAGE 'sql';
在上述函数中,文档代码作为第一个参数传递,第二个参数是格式代码(指示在验证中使用哪个 DTD),"CONVERT" 函数用于将文档编码转换为 UNICODE,因为 XML 操作函数仅支持 UNICODE。此外,还可以创建特定于存储 XML 的数据类型,以便自动执行这些检查,但这里不深入讨论,因为这将需要单独的文章。第二个函数 pgxml_xpath 使您能够从查询的 XML 文档中提取特定数据。例如,您使用一个字段来存储表示特定产品技术规格的 XML 文档。假设该产品表具有以下结构:
CREATE TABLE Produtos (
id_produto Serial,
id_tipo_produto,
nome varchar(50),
descricao text,
especificacoes_tecnicas text);
在 "especificacoes_tecnicas" 字段中,插入包含产品所有规格的 XML 文档。该 XML 可能如下所示:
<especificacoes>
<medidas>
<peso>
13 Kg
</peso>
<altura>
1,77 m
</altura>
<largura>
1,50 m
</largura>
</medidas>
</especificacoes>
如果我想列出所有类型为 1 的产品及其相应的重量,我可以使用包含 XPath 函数的 SQL:
SELECT nome, pgxml_xpath(string_contendo_dtd || especificacoes_tecnicas, '//especificacoes/medidas/peso/text()','','') as peso
FROM Produtos
WHERE id_tipo_produto = 1;
在本例中,我手动将包含 XML 文档 DTD 的字符串连接到函数的第一个参数中,该参数应接收要处理的 XML 文档。在第二个参数中,我传递了一个字符串,指定在 XML 中要执行的搜索,在本例中为://especificacoes/medidas/peso/text(),这意味着我要获取 "especificacoes" 下 "medidas" 下 "peso" 元素的文本内容。字符串开头的双斜杠 (//) 表示要处理所有子元素(在本例中,所有 "especificacoes" 的子元素),字符串末尾的 text() 表示我想要返回 "peso" 元素的内容(根据示例,为:"13 Kg"),而不是整个元素(为:" 13 Kg ")。我们可以使用更复杂的文档来更好地探索 XPath 的潜力,让我们利用之前的示例,并在 XML 的某些元素中添加属性:
<especificacoes>
<medidas>
<peso unidade="kg">
13 kg
</peso>
<peso unidade="lbs">
28,7 lbs
</peso>
<altura>
1,77 m
</altura>
<largura>
1,50 m
</largura>
</medidas>
</especificacoes>
现在,假设我想获得与前一个示例相同的返回值(类型为 1 的产品及其相应的重量),但这次我想过滤 "peso" 元素,以便它只返回那些以磅为单位的元素:
SELECT nome, pgxml_xpath(string_contendo_dtd || especificacoes_tecnicas, '//especificacoes/medidas/peso[@unidade=''lbs'']/text()','','') as peso
FROM Produtos WHERE id_tipo_produto = 1;
当然,这里使用的示例非常简单,但应该说明了此工具的潜力,因为就像我在特定属性上使用过滤器一样,我也可以使用 XPath 语言定义的其他功能。还可以使用简化特定信息组搜索的函数,甚至可以使用返回 XML 文档作为其他表的函数。另一个有趣的可能性是在数据库中存储以 xml 格式表示的对象,以便我可以搜索存储的对象并直接从数据库字段实例化对象。此外,还有许多其他可能性,这仅仅是创造力和学习的问题。
XPath 语言规范可以在以下网站找到:http://www.w3.org/TR/xpath
一个提供关于 XPath 的良好文档的网站是微软关于 XPath 的网站。
注意
对于想要在 PostgreSQL 中使用 XML 的人来说,一个重要的注意事项是,XML 函数只支持使用 UNICODE 编码的文本,并且要注意数据库的 "encoding" 属性(编码)。编码是在创建数据库时在 CREATE DATABASE 命令中定义的。如果在创建数据库时没有指定编码,则使用在 initdb 命令中定义的默认编码。如果它不是 UNICODE,请不要担心,PostgreSQL 有一个转换函数可以用于将字段从一种编码转换为另一种编码,该函数为 convert。
convert('Texto', 'Codificação_Origem', 'Codificação_Destino')
Java 持久性 API (JPA) 中的 XML
我们知道,对象关系映射通常会对性能以及数据库的正确使用产生负面影响。但是,由于在软件开发期间的高生产力,该技术的使用频率越来越高。使用对象关系映射框架会限制数据库中各种功能的使用,例如触发器、视图、过程,甚至限制使用 PostgreSQL 的原生 XML 列。但是,通过对 JDBC 驱动程序进行一些修改,可以透明地实现原生 XML 列的映射。在 支持 XML 的 JDBC4 驱动程序 页面上,您可以找到修改后的 JDBC4 驱动程序的下载链接,该驱动程序允许这种映射。该驱动程序拥有自由软件许可证,可以不受限制地修改和分发。