Postgresql: ¿Cómo cambiar el valor de un atributo en una columna XML?

Necesito cambiar el valor de un atributo XML almacenado en una columna usando el tipo de datos XML en una tabla antes de devolverlo al cliente.

Ahora mismo uso un cursor, Obtener xml, echarlo a VARCHAR, analizarlo, cambiar el valor del atributo (o agréguelo si no está presente), ponerlo en la tabla temporal y devolver datos de la tabla temporal. Todo se hace en un procedimiento almacenado (pl/pgsql).

Me pregunto si hay una forma más limpia de hacer esto.

preguntado el 26 de abril de 12 a las 08:04

No conozco una función para reemplazar atributos en XML. Pero tal vez su código aún podría mejorarse. Ayudaría si lo incluyera en la pregunta. -

2 Respuestas

Puede usar el XML :: LibXML en un parche de PL/PerlU (o PL/Perl, si puede precargar XML::LibXML en plperl.on_init en tu postgresql.conf) Me gusta esto:

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;
$$;

Entonces puedes usarlo así:

try=# SELECT replace_attribute(
    '<foo id="blah">hi</foo>',
    'id',
    'whatever'
);
      replace_attribute      
-----------------------------
 <foo id="whatever">hi</foo>+

Hay bastante flexibilidad en la expresión XPath para findnodes(), en caso de que necesite más que eso.

contestado el 06 de mayo de 12 a las 07:05

Gracias, una pregunta más: ¿necesito convertir el tipo de datos xml a una cadena o pl/perl puede trabajar directamente con el tipo de datos xml? ¿Debería preocuparme por los gastos generales si esta función se llama mucho? - probador.uno

Se convertirá automáticamente en texto antes de pasar a PL/Perl. Eso es lo que hace el ejemplo aquí. - teoría

Versión de 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')

Respondido 26 ago 13, 18:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.