クライアントに返す前に、テーブルの XML データ型を使用して、列に格納されている XML 属性の値を変更する必要があります。
今、私はcursorを使用し、 xmlを取得し、それをにキャストしVARCHAR
、解析し、属性値を変更(または存在しない場合は追加) し、一時テーブルに入れ、一時テーブルからデータを返します。すべてがストアド プロシージャ (pl/pgsql) で行われます。
これを行うためのよりクリーンな方法があるのだろうか?
クライアントに返す前に、テーブルの XML データ型を使用して、列に格納されている XML 属性の値を変更する必要があります。
今、私はcursorを使用し、 xmlを取得し、それをにキャストしVARCHAR
、解析し、属性値を変更(または存在しない場合は追加) し、一時テーブルに入れ、一時テーブルからデータを返します。すべてがストアド プロシージャ (pl/pgsql) で行われます。
これを行うためのよりクリーンな方法があるのだろうか?
次のように、PL /PerlU関数(またはXML ::LibXMLをプリロードできる場合はPL/Perl)で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>+
findnodes()
それ以上が必要な場合に備えて、XPath式にはかなりの柔軟性があります。
Python バージョン:
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')