【问题标题】:How to compare XML for equality in PostgreSQL如何在 PostgreSQL 中比较 XML 是否相等
【发布时间】:2016-12-29 05:15:48
【问题描述】:

我在 PostgreSQL 中创建了一个包含 XML 列的表。我正在为该列使用text 数据类型。现在我有一个示例 XML,它存储在表中的一个字段中,如下所示:

<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>

现在我创建了一个比较 2 个 XML 数据的程序。如果找到 XML 数据,则返回 true,否则返回 false

问题是如果XML数据存储在表格中的一行中

<note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>

然后它给出所需的输出,但如果它存储在不同的行中,则返回null

我的过程如下所示

CREATE OR REPLACE FUNCTION comparexml(p_name_in VARCHAR(255), p_xml_data_in text, out p_id integer)AS $BODY$

DECLARE
V_ID INTEGER;

BEGIN

SELECT id INTO v_id
FROM employee 
WHERE XML_DATA = p_xml_data_in and
NAME=p_name_in;


IF(v_id IS NULL) THEN
V_ID := 0;
ELSE
V_ID := 1;
END IF;

p_id=v_id;

END;
$BODY$ LANGUAGE plpgsql;

【问题讨论】:

  • 显示您的查询不知道您想要什么。
  • @EvanCarroll - 我的函数如下所示 CREATE OR REPLACE FUNCTION comparexml(p_name_in VARCHAR(255), p_xml_data_in text, out p_id integer)AS $BODY$ DECLARE V_ID INTEGER; BEGIN SELECT id INTO v_id FROM employee WHERE XML_DATA = p_xml_data_in 和 NAME=p_name_in;如果(v_id 为空)然后 V_ID := 0;否则 V_ID := 1;万一; p_id=v_id;结尾; $BODY$ 语言 plpgsql;
  • 更新问题并格式化那个东西...
  • @EvanCarroll - 完成!
  • 你的函数没有返回任何东西。你说你比较两个xml,但你在代码中只有检查它是否为空

标签: xml postgresql comparison


【解决方案1】:

我不确定您为什么关心一个 XML 文档是否等于另一个。如果您使用此限定条件进行搜索,您可能(但不一定)做错了。这不是 XML 的用途。您可以搜索 XML 中是否存在某些内容。

CREATE TABLE foo AS SELECT xmlparse(DOCUMENT xml) AS xmlcol
FROM ( VALUES
  ($$<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
$$),
  ($$ <note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note> $$)
) AS t(xml);

但你不应该关心foo.xmlcol = p_xml_data_in。试一试

  • 桌子上有一个 id。
  • xml 中的 id。

也就是说,如果这对您很重要,您也许可以bribe the guy who write this answer and committed the xml code。 PostgreSQL 目前没有canonicalxml 类型,但它可以实现,它在TODO 上(并且可能会在那里保留很长时间)

XML Canonical:将 XML 文档转换为规范形式以进行比较。 libxml2 对此有支持。

【讨论】:

  • 我做了一些研究并尝试了一些实际场景,我知道这不是同行或换行 xml 的问题(如问题所述)。 Postgre 可以比较这两种类型的 xml。实际上,这取决于它如何存储在表中。 ToveJani提醒这个周末别忘了我!
  • --上述评论的继续这里这个xml已经由人在一行中发送但在表中它存储在两行中(根据此评论中给出的示例,它采用了新行来自 ng> 标签)。该人不知道它是如何存储在表中的。因此,在比较时,他将在单行中传递 xml(与在插入时传递的方式相同),这将比较存储在 2 行中的表的 xml(来自 ng> 标记的新行,这将但显然会给出不同的结果)。
  • --上述评论的继续。所以实际上这就是区别所在。如果有人可以在这方面提供帮助,那就太好了。
  • 这根本不是真的。 PostgreSQL 对 XML 数据类型什么都不做。也许正在使用的寻呼机正在包装它。如果您使用的是 linux,请尝试 PAGER="less -S" psql
【解决方案2】:

plpythonlxml 的帮助下,您可以稍微清除一下您的xml:

CREATE OR REPLACE FUNCTION xmlclean(xml_doc text) RETURNS text AS
$BODY$

from lxml import etree
parser = etree.XMLParser(remove_blank_text=True)

return etree.tostring(etree.XML(xml_doc, parser=parser))

$BODY$
LANGUAGE plpythonu;

示例用法:

postgres=# select xmlclean('<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don''t forget me this weekend!</body>
</note>');
                                                             xmlclean                                             
------------------------------------------------------------------------------------------------------------------
 <note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>
(1 row)

和:

postgres=# select xmlclean('<note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don''t forget me this weekend!</body></note>');
                                                     xmlclean                                                     
------------------------------------------------------------------------------------------------------------------
 <note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>
(1 row)

然而,它仍然不是完美的:如果标签顺序不同怎么办(我猜语义会保持不变,即它们应该被认为是相等的,但显然它们不会)

【讨论】:

猜你喜欢
  • 2014-09-20
  • 2012-02-15
  • 2013-03-29
  • 2010-12-10
  • 1970-01-01
  • 2015-03-13
  • 2015-09-16
  • 1970-01-01
相关资源
最近更新 更多