Por ello esta entrada, donde la cosa es sencilla, en primer lugar tengo un xml con una estructura del tipo colegio -> alumnos -> materias -> libros, es decir un colegio con muchos alumnos, estos alumnos pueden tener muchas materias y cada materia muchos libros... ni mas ni menos que eso.
comenzando en 3... 2... 1...
Primero los scripts en donde creo cada uno de los objetos que voy a utilizar, incluida una tabla en donde va a estar alojado mi xml.
Esto último puede o no ser así, ya que el xml puede llegar a nuestro programa de distintas formas, como un archivo en un directorio de base de datos, por ejemplo.
Pero para hacer mas sencillo el ejemplo, cree una tabla con un campo del tipo CLOB, dónde esta el xml que contiene los datos a parsear y cargar.
Primero la tabla y el insert del xml en el campo:
create table colegio (
campoclob clob
)
/
insert into colegio values ('
<!--?xml version="1.0" encoding="ISO-8859-1"?-->
<xml>
<colegio>
<alumnos>
<alumno>
<id_alumno>1</id_alumno>
<nombre>alumno1</nombre>
<materias>
<materia>
<nommat>matematica</nommat>
<libros>
<libro>
<titulo>calculo1</titulo>
</libro>
<libro>
<titulo>introd</titulo>
</libro>
<libro>
<titulo>algebra</titulo>
</libro>
</libros>
</materia>
<materia>
<nommat>castellano</nommat>
<libros>
<libro>
<titulo>analisis sintactico</titulo>
</libro>
<libro>
<titulo>lengua</titulo>
</libro>
<libro>
<titulo>cortazae 1</titulo>
</libro>
</libros>
</materia>
</materias>
</alumno>
<alumno>
<id_alumno>2</id_alumno>
<nombre>alumno2</nombre>
<materias>
<materia>
<nommat>matematica</nommat>
<libros>
<libro>
<titulo>xxxx</titulo>
</libro>
<libro>
<titulo>analisis 1</titulo>
</libro>
</libros>
</materia>
<materia>
<nommat>castellano</nommat>
<libros>
<libro>
<titulo>nos e que</titulo>
</libro>
</libros>
</materia>
</materias>
</alumno>
</alumnos>
</colegio>
</xml>
')
/
Ahí esta el xml del que tanto hablamos.
Ahora como segundo paso creamos nuestros objetos, y acá hacemos un parate.
Cuando lo creé para el fin del ejemplo, los creé globales, pero tambien se pueden crear de forma local solo para usarlos en bloque anónimo.
CREATE OR REPLACE TYPE LIBRO AS OBJECT (
TITULO VARCHAR2(50)
)
/
CREATE OR REPLACE TYPE LIBROS AS TABLE OF LIBRO
/
CREATE OR REPLACE TYPE LIBROSS AS OBJECT(
TLIBRO LIBROS
)
/
CREATE OR REPLACE TYPE TLIBROSS AS TABLE OF LIBROSS;
CREATE OR REPLACE TYPE MATERIA AS OBJECT (
MATERIA VARCHAR2(50),
MALIBROS TLIBROSS
)
/
CREATE OR REPLACE TYPE MATERIAS AS TABLE OF MATERIA
/
CREATE OR REPLACE TYPE MATERIASS AS OBJECT(
TMATERIA MATERIAS
)
/
CREATE OR REPLACE TYPE TMATERIASS AS TABLE OF MATERIASS
/
CREATE OR REPLACE TYPE ALUMNO AS OBJECT (
ID_ALUMNO NUMBER,
NOMBRE VARCHAR2(50),
ALMAT TMATERIASS
)
/
CREATE OR REPLACE TYPE ALUMNOS AS TABLE OF ALUMNO
/
CREATE OR REPLACE TYPE ALUMNOSS AS OBJECT(
TALUMNO ALUMNOS
)
/
CREATE OR REPLACE TYPE TALUMNOSS AS TABLE OF ALUMNOSS
/
Bien ahí esta el objeto alumno, el objeto materia y el objeto libro. Ahora vamos a parsear el xml y mostrar los datos que están ahí, y también a cargarlos:
DECLARE
BOOK LIBRO;
BOOKS LIBROS;
BOOKSS LIBROSS;
TBOOKSS TLIBROSS;
MATER MATERIA;
MATERS MATERIAS;
MATERSS MATERIASS;
TMATERSS TMATERIASS;
PUPIL ALUMNO;
PUPILS ALUMNOS;
PUPILSS ALUMNOSS;
TPUPILSS TALUMNOSS;
schoolclob clob;
v_parser xmlparser.parser;
schooldoc xmldom.domdocument;
infonodelist xmldom.domnodelist;
infonodelist1 xmldom.domnodelist;
infonodelist2 xmldom.domnodelist;
infonode xmldom.domnode;
infonode1 xmldom.domnode;
infonode2 xmldom.domnode;
BEGIN
--INSTANCIO E INICIALIZO
BOOKS:=LIBROS(NULL);
BOOK:=LIBRO(NULL);
BOOKSS:= LIBROSS(NULL);
TBOOKSS :=TLIBROSS(NULL);
MATER:=MATERIA(NULL,NULL);
MATERS:=MATERIAS(NULL);
MATERSS := MATERIASS(NULL);
TMATERSS := TMATERIASS(NULL);
PUPIL:=ALUMNO(NULL,NULL,NULL);
PUPILS:=ALUMNOS(NULL);
PUPILSS :=ALUMNOSS(NULL);
TPUPILSS :=TALUMNOSS(NULL);
--saco el campo clob y lo meto en la variable
SELECT DBMS_LOB.substr(campoclob,DBMS_LOB.getlength(campoclob),1)
INTO schoolclob
FROM COLEGIO;
--comienzo el parseo
v_parser := xmlparser.newparser;
dbms_xmlparser.setvalidationmode (v_parser, FALSE);
dbms_xmlparser.parseclob (v_parser, schoolclob);
schooldoc := dbms_xmlparser.getdocument (v_parser);
-- Se libera el parser que ya no se utiliza
dbms_xmlparser.freeparser (v_parser);
BEGIN
-- Se analizan nodos del documento y se actualizan las tablas
infonodelist := dbms_xslprocessor.selectnodes (DBMS_xmldom.makenode(schooldoc),'xml/colegio/alumnos/alumno');
DBMS_OUTPUT.PUT_LINE('1');
FOR al IN 0 .. DBMS_xmldom.getlength(infonodelist) - 1 LOOP
DBMS_OUTPUT.PUT_LINE('2');
infonodelist1 := dbms_xslprocessor.selectnodes (DBMS_xmldom.makenode (schooldoc),'xml/colegio/alumnos/alumno['||to_char(al+ 1)||']/materias/materia');
FOR ma IN 0 .. DBMS_xmldom.getlength(infonodelist1) -1 LOOP
infonodelist2 := dbms_xslprocessor.selectnodes (xmldom.makenode (schooldoc),'xml/colegio/alumnos/alumno['||to_char(al+ 1)||']/materias/materia['||to_char(ma+ 1)||']/libros/libro');
FOR li IN 0 .. DBMS_xmldom.getlength (infonodelist2) - 1 LOOP
infonode2:= xmldom.item (infonodelist2,li);
dbms_output.put_line(xslprocessor.valueof (infonode2,'titulo'));
BOOKS.EXTEND;
BOOKS(BOOKS.COUNT) := LIBRO(xslprocessor.valueof (infonode2,'titulo'));
END LOOP;
TBOOKSS.EXTEND;
TBOOKSS(TBOOKSS.COUNT) := LIBROSS(BOOKS);
infonode1 := xmldom.item (Infonodelist1, ma);
dbms_output.put_line(xslprocessor.valueof (infonode1,'nommat'));
MATERS.EXTEND;
MATERS(MATERS.COUNT) := MATERIA(xslprocessor.valueof (infonode1,'nommat'),
TBOOKSS);
END LOOP;
TMATERSS.EXTEND;
TMATERSS(TMATERSS.COUNT) := MATERIASS(MATERS);
infonode := xmldom.item (Infonodelist, al);
dbms_output.put_line(xslprocessor.valueof (infonode,'nombre'));
PUPILS.EXTEND;
PUPILS(PUPILS.COUNT) := alumno(TO_NUMBER(xslprocessor.valueof (infonode,'id_alumno')),
xslprocessor.valueof (infonode,'nombre'),
TMATERSS);
END LOOP;
END;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(SQLERRM);
END;
Bien, utilizamos algunos paquetes de base de datos que antes de ejecutar y compilar este ejemplo deben estar instalados, como son:
dbms_xmlparser
dbms_lob
dbms_xmldom
dbms_xslprocessor
En fin, para la proxima, como recuperar los datos de esos tipos... escucho ofertas.