Para generar XML desde PL/SQL existen diversos métodos que van desde una select que utilice funciones XML_TYPE al empleo de los paquetes PL/SQL integrados en Oracle. En nuestro ejemplo vamos a utilizar DBMS_XMLDOM para montar un XML como este:
<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
<node01 Attr01="Atribute 01" Attr02="Atribute 02">Node 01 text</node01>
<node02>Node 02 text</node02>
</root>
Paquete de utilidades XML
El primer paso consiste en compilar el siguiente paquete en la base de datos. Esto nos va a permitir agilizar la creación de los nodos utilizando una serie de tablas para registrar cada nodo y el procedimiento de de escritura de estos nodos en el XML que estemos generando:
CREATE OR REPLACE PACKAGE create_xml IS
-- Declare XML types
type ry_xmlattrib is record (
p_attrib_name varchar2(512),
p_attrib_value varchar2(32767)
);
type ty_xmlattrib is table of ry_xmlattrib;
type ry_xmlelement is record (
p_parent dbms_xmldom.DOMNode,
p_element_name varchar2(512),
p_element dbms_xmldom.DOMElement,
p_attribs ty_xmlattrib,
p_node dbms_xmldom.DOMNode,
p_text_value varchar2(32767),
p_text dbms_xmldom.DOMText,
p_textnode dbms_xmldom.DOMNode
);
type ty_xmlelement is table of ry_xmlelement;
type ty_varchar2 is table of varchar2(32767) index by varchar2(64);
-- Add node to ty_xmlelement
procedure add_node(
p_tb_xmlelements in out ty_xmlelement,
p_tb_index_nodes in out ty_varchar2,
p_index_id in varchar2,
p_parent_index_id in varchar2,
p_node_name in varchar2,
p_text_value in varchar2,
p_attribs in ty_xmlattrib
);
-- Write node to XML
procedure write_node(
p_domdoc in out dbms_xmldom.DOMDocument,
p_reg_nodo in out ry_xmlelement
);
END create_xml;
CREATE OR REPLACE PACKAGE BODY create_xml AS
-- Add node to ty_xmlelement
procedure add_node(
p_tb_xmlelements in out ty_xmlelement,
p_tb_index_nodes in out ty_varchar2,
p_index_id in varchar2,
p_parent_index_id in varchar2,
p_node_name in varchar2,
p_text_value in varchar2,
p_attribs in ty_xmlattrib
)
is
begin
-- Add node
p_tb_xmlelements.extend;
p_tb_index_nodes( p_index_id ) := p_tb_xmlelements.last;
p_tb_xmlelements( p_tb_index_nodes( p_index_id ) ).p_attribs := create_xml.ty_xmlattrib();
p_tb_xmlelements( p_tb_index_nodes( p_index_id ) ).p_parent := p_tb_xmlelements( p_tb_index_nodes( p_parent_index_id ) ).p_node;
p_tb_xmlelements( p_tb_index_nodes( p_index_id ) ).p_element_name := p_node_name;
p_tb_xmlelements( p_tb_index_nodes( p_index_id ) ).p_text_value := p_text_value;
-- Add attribs
if p_attribs is not null then
p_tb_xmlelements( p_tb_index_nodes( p_index_id ) ).p_attribs := create_xml.ty_xmlattrib();
for i_att in 1..p_attribs.count() loop
p_tb_xmlelements( p_tb_index_nodes( p_index_id ) ).p_attribs.extend();
p_tb_xmlelements( p_tb_index_nodes( p_index_id ) ).p_attribs(i_att).p_attrib_name := p_attribs(i_att).p_attrib_name;
p_tb_xmlelements( p_tb_index_nodes( p_index_id ) ).p_attribs(i_att).p_attrib_value := p_attribs(i_att).p_attrib_value;
end loop;
end if;
end add_node;
-- Write node to XML
procedure write_node(
p_domdoc in out dbms_xmldom.DOMDocument,
p_reg_nodo in out ry_xmlelement
)
is
begin
-- Write node
p_reg_nodo.p_element := dbms_xmldom.createElement(p_domdoc, p_reg_nodo.p_element_name );
if p_reg_nodo.p_attribs is not null then
if p_reg_nodo.p_attribs.count() > 0 then
for i_att in 1..p_reg_nodo.p_attribs.count() loop
dbms_xmldom.setAttribute(
p_reg_nodo.p_element,
p_reg_nodo.p_attribs(i_att).p_attrib_name,
p_reg_nodo.p_attribs(i_att).p_attrib_value
);
end loop;
end if;
end if;
p_reg_nodo.p_node := dbms_xmldom.appendChild(p_reg_nodo.p_parent,dbms_xmldom.makeNode(p_reg_nodo.p_element));
p_reg_nodo.p_text := dbms_xmldom.createTextNode(p_domdoc, p_reg_nodo.p_text_value );
p_reg_nodo.p_textnode := dbms_xmldom.appendChild(p_reg_nodo.p_node,dbms_xmldom.makeNode(p_reg_nodo.p_text));
end write_node;
END create_xml;
Ejemplo
El siguiente procedimiento utiliza el paquete create_xml para generar el XML de ejemplo con el que se ha iniciado esta entrada:
-- Generate XML (example)
CREATE OR REPLACE PROCEDURE xml_example
IS
l_domdoc dbms_xmldom.DOMDocument;
l_root_node dbms_xmldom.DOMNode;
tb_xmlelements create_xml.ty_xmlelement := create_xml.ty_xmlelement();
tb_index create_xml.ty_varchar2;
tb_attribs create_xml.ty_xmlattrib := create_xml.ty_xmlattrib();
v_buffer varchar2(32767);
BEGIN
-- Create an empty XML document
l_domdoc := dbms_xmldom.newDomDocument;
-- Set version
dbms_xmldom.setVersion(l_domdoc, '1.0');
dbms_xmldom.setCharset(l_domdoc, 'ISO-8859-1');
-- Create a root node
l_root_node := dbms_xmldom.makeNode(l_domdoc);
tb_xmlelements.extend;
tb_index('root') := tb_xmlelements.last;
tb_xmlelements(tb_index('root')).p_attribs := create_xml.ty_xmlattrib();
tb_xmlelements(tb_index('root')).p_parent := l_root_node;
tb_xmlelements(tb_index('root')).p_element_name := 'root';
tb_xmlelements(tb_index('root')).p_text_value := '';
create_xml.write_node(l_domdoc, tb_xmlelements(tb_index('root')));
-- Create a new node with text and attributes
tb_attribs.extend();
tb_attribs(1).p_attrib_name := 'Attr01';
tb_attribs(1).p_attrib_value := 'Atribute 01';
tb_attribs.extend();
tb_attribs(2).p_attrib_name := 'Attr02';
tb_attribs(2).p_attrib_value := 'Atribute 02';
create_xml.add_node(tb_xmlelements, tb_index, 'node01', 'root', 'node01', 'Node 01 text', tb_attribs );
create_xml.write_node(l_domdoc, tb_xmlelements(tb_index('node01')));
-- Create a additional node with text
tb_attribs.delete;
create_xml.add_node(tb_xmlelements, tb_index, 'node02', 'root', 'node02', 'Node 02 text', tb_attribs );
create_xml.write_node(l_domdoc, tb_xmlelements(tb_index('node02')));
-- Result
dbms_xmldom.writeToBuffer(l_domdoc, v_buffer);
dbms_output.put_line(v_buffer);
dbms_xmldom.freeDocument(l_domdoc);
END xml_example;
Encoding
Hay que tener especial cuidado con la declaración del encoding del XML. La forma de declararlo varía dependiendo del destino al que se vaya a enviar el XML: salida dbms_output, un XMLType o un Lob. En algunos conextos, en lugar de utilizar el procedimiento dbms_xmldom.setCharset(l_domdoc, ‘ISO-8859-1’) hay que manipular el procedimiento setVersion de la siguiente forma:
dbms_xmldom.setVersion(l_domdoc, '1.0" encoding="ISO-8859-1');
Me gusta esto:
Me gusta Cargando...