在将其返回给客户端之前,我需要使用表中的 XML 数据类型更改存储在列中的 XML 属性的值。
现在我使用cursor,获取xml,将其转换为VARCHAR
,解析它,更改属性值(或者如果它不存在则添加它),将其放入临时表并从临时表返回数据。一切都在存储过程(pl/pgsql)中完成。
我想知道是否有更清洁的方法来做到这一点?
在将其返回给客户端之前,我需要使用表中的 XML 数据类型更改存储在列中的 XML 属性的值。
现在我使用cursor,获取xml,将其转换为VARCHAR
,解析它,更改属性值(或者如果它不存在则添加它),将其放入临时表并从临时表返回数据。一切都在存储过程(pl/pgsql)中完成。
我想知道是否有更清洁的方法来做到这一点?
您可以在PL/PerlU函数(或 PL/Perl,如果您可以在中预加载 XML::LibXML)中使用XML ::LibXML,如下所示:plperl.on_init
postgresql.conf
CREATE EXTENSION IF NOT EXISTS plperlu;
CREATE OR REPLACE FUNCTION replace_attribute(
xml xml,
attr text,
val text
) RETURNS XML LANGUAGE plperlu AS $$
my ($xml, $attr, $val) = @_;
use XML::LibXML;
my $dom = XML::LibXML->load_xml(string => $xml);
for my $elem ($dom->findnodes("*[\@$attr]")) {
$elem->setAttribute($attr => $val);
}
return $dom->serialize;
$$;
然后你可以像这样使用它:
try=# SELECT replace_attribute(
'<foo id="blah">hi</foo>',
'id',
'whatever'
);
replace_attribute
-----------------------------
<foo id="whatever">hi</foo>+
在 XPath 表达式 to 中有相当多的灵活性findnodes()
,以防您需要更多。
蟒蛇版本:
create or replace function replace_attrib(data xml, attr text, val text)
returns xml as
$$
import xml.etree.ElementTree as ET
r = ET.fromstring(data)
r.attrib[attr] = val
return ET.tostring(r)
$$ language plpython3u;
select replace_attrib('<foo id="blah">hi</foo>', 'id', 'whatever')