Möchte man in PL/SQL XML-Dokumente erstellen und verwenden, hat man mehrere Möglichkeiten. Im Folgenden werden einige Möglichkeiten aufgezeigt und anhand eines Beispiels werden zwei XML-Dokumente zusammengeführt.
Bei sehr kleinen und einfachen Strukturen reicht es, einen passenden String in eine XMLTYPE Variable zu schreiben:
DECLARE l_xml_db XMLTYPE := xmltype('<ORACLE><Version>11g</Version><Version>12c</Version></ORACLE>'); BEGIN DBMS_OUTPUT.put_line(l_xml_db.getstringval()); END; /
Möchte man die Ergebnismenge eines Select Statements direkt in eine XML-Struktur überführen lohnt ein Blick auf das DBMS_XMLGEN Package:
DECLARE l_xml XMLTYPE; lh_xmlctx DBMS_XMLGEN.ctxhandle; BEGIN lh_xmlctx := DBMS_XMLGEN.newcontext('SELECT sysdate systimestamp FROM dual'); DBMS_XMLGEN.setrowsettag(lh_xmlctx, 'Uhrzeiten'); DBMS_XMLGEN.setrowtag(lh_xmlctx, 'Aktuell'); l_xml := DBMS_XMLGEN.getxmltype(lh_xmlctx); DBMS_XMLGEN.closecontext(lh_xmlctx); DBMS_OUTPUT.put_line(l_xml.getclobval); END; /
Die umfangreichsten Möglichkeiten bekommt man mit dem – in der Oracle XML DB enthaltenen – Package DBMS_XMLDOM. Dieses Package bietet umfangreiche Bearbeitungs- und Validierungs-Möglichkeiten, ist jedoch in der Anwendung komplexer als DBMS_XMLGEN bzw. XMLTYPE.
In dem folgenden Beispiel wird gezeigt wie zwei bereits bestehende XML-Dokumente mittels DBMS_XMLDOM in ein Dokument zusammengeführt werden. Zu Beginn wird das folgende XML-Dokument aufgebaut in welches die weiteren Daten importiert werden sollen.
<Versionen> <Datenbanken> </Datenbanken> <Software> </Software> </Versionen>
Die Aufbau des Dokuments und der Import der Daten wird durch das folgende PL/SQL Programm durchgeführt. Zur Veranschaulichung wird das finale XML-Dokument über DBMS_OUTPUT ausgegeben.
DECLARE lh_xmldoc DBMS_XMLDOM.domdocument; l_node_root DBMS_XMLDOM.domnode; l_node_versionen DBMS_XMLDOM.domnode; l_node_datenbanken DBMS_XMLDOM.domnode; l_node_software DBMS_XMLDOM.domnode; --Knoten <Datenbank> l_subnode_db DBMS_XMLDOM.domnode; l_xml_db XMLTYPE := xmltype('<ORACLE><Version>11g</Version><Version>12c</Version></ORACLE>'); --Knoten <OraInfo> l_subnode_orainfo DBMS_XMLDOM.domnode; l_xml_orainfo CLOB := '<OraInfo><Version>1</Version></OraInfo>'; --Debug l_buffer_root VARCHAR2(1000); BEGIN --DOM Document erzeugen lh_xmldoc := DBMS_XMLDOM.newdomdocument; --Root Knoten l_node_root := DBMS_XMLDOM.makenode(lh_xmldoc); --<oracle> Knoten erzeugen l_node_versionen := DBMS_XMLDOM.appendchild(l_node_root, DBMS_XMLDOM.makenode(DBMS_XMLDOM.createelement(lh_xmldoc, 'Versionen'))); --Knoten <Datenbanken> erzeugen l_node_datenbanken := DBMS_XMLDOM.appendchild(l_node_versionen, DBMS_XMLDOM.makenode(DBMS_XMLDOM.createelement(lh_xmldoc, 'Datenbanken'))); --Knoten <Software> erzeugen l_node_software := DBMS_XMLDOM.appendchild(l_node_versionen, DBMS_XMLDOM.makenode(DBMS_XMLDOM.createelement(lh_xmldoc, 'Software'))); --Inhalt aus l_xml_db in lh_xmldoc importieren --Anmerkung: getdocumentelement referenziert den Root-Knoten des Dokuments l_subnode_db := DBMS_XMLDOM.appendchild( l_node_datenbanken, DBMS_XMLDOM.importnode( lh_xmldoc, DBMS_XMLDOM.makenode(DBMS_XMLDOM.getdocumentelement(DBMS_XMLDOM.newdomdocument(l_xml_db))), TRUE)); --Inhalt aus l_xml_db in lh_xmldoc importieren --Anmerkung: getdocumentelement referenziert den Root-Knoten des Dokuments l_subnode_orainfo := DBMS_XMLDOM.appendchild( l_node_software, DBMS_XMLDOM.importnode( lh_xmldoc, DBMS_XMLDOM.makenode(DBMS_XMLDOM.getdocumentelement(DBMS_XMLDOM.newdomdocument(l_xml_orainfo))), TRUE)); ---DEBUG START--- DBMS_XMLDOM.writetobuffer(l_node_root, l_buffer_root); DBMS_OUTPUT.put_line(l_buffer_root); ---DEBUG ENDE--- EXCEPTION WHEN OTHERS THEN RAISE; END; /
Übersicht der verwendeten Variablen und deren Zweck:
- lh_xmldoc
Referenz auf Ziel XML-Dokument - l_node_root
Referenz auf Rootknoten im Ziel XML-Dokument - l_node_versionen
Referenz auf <Versionen> Knoten - l_node_datenbanken
Referenz auf <Datenbanken> Knoten - l_node_software
Referenz auf <Software> Knoten - l_subnode_db
Referenz auf importierten Knoten <ORACLE> - l_xml_db
Quell XML-Dokument mit <ORACLE> Knoten - l_subnode_orainfo
Referenz auf importierten Knoten <OraInfo> - l_xml_orainfo
Quell XML-Dokument mit <OraInfo> Knoten - l_buffer_root
Debug Buffer-Variable zum Ausgeben des Gesamtdokuments
Das Vorgehen zum Import von XML-Dokumenten ist in beiden Fällen identisch:
DBMS_XMLDOM.appendchild( l_node_datenbanken, DBMS_XMLDOM.importnode( lh_xmldoc, DBMS_XMLDOM.makenode(DBMS_XMLDOM.getdocumentelement(DBMS_XMLDOM.newdomdocument(l_xml_db))), TRUE));
Mit der DBMS_XMLDOM.newdomdocument Funktion wird die XMLTYPE / CLOB Variable in ein domdocument konvertiert. Anschießend wird über DBMS_XMLDOM.getdocumentelement eine Referenz auf den Rootknoten gesetzt und an die übergeordnete DBMS_XMLDOM.makenode Funktion übergeben. Diese baut einen neuen XML-Knoten welcher nun über die DBMS_XMLDOM.importnode Funktion in das XML-Dokument lh_xmldoc importiert wird. Da der obrige Code die Variable l_xml_db importiert, werden die Daten über DBMS_XMLDOM.appendchild als Subknoten an l_node_datenbanken angehangen.
Es stellt sich jedoch die Frage warum man sich den ganzen Aufwand machen möchte. Wäre es nicht einfacher die XML-Strings bei Bedarf zusammenzubauen und weiter in einer XMLTYPE / CLOB Variable zu speichern? Hier kann gesagt werden, dass das DBMS_XMLDOM Package einige wesentliche Vorteile mitbringt.
- Erweiterte XML Fehlerprüfung
Fehler in der XML Struktur welche in einer XMLTYPE / CLOB Variable nicht immer erkannt werden, werden in einem domdocument als Exception gemeldet und können in einem PL/SQL Exception Block behandelt werden. - Es können direkt Dateien in einem frei wählbaren Zeichensatz geschrieben werden
Zwar können auch XMLTYPE und CLOB Dokumente in das Dateisystem geschrieben werden, dies jedoch nur möglich mit den in NLS_CHARACTERSET / NLS_NCHAR_CHARACTERSET eingetragenen Zeichensätzen. - Zugriff auf Oracle XML DB Funktionalität
Die Oracle XML DB bietet eine vollständige XML Implementierung inklusive Datenmanipulation, Validierung mittels XML Schema Definitionen (XSD), und vielem mehr.
Das oben gezeigte Vorgehen ermöglicht es bereits bestehende Programmstrukturen welche zum Beispiel auf DBMS_XMLGEN aufbauen, bestehen zu lassen und diese in die DBMS_XMLDOM Strukturen zu importieren. Dies kann den Migrationsaufwand erheblich verringern.