Generarea documentelor XML

In Oracle există mai multe posibilităti de generare a documentelor XML folosind rezultatul unei interogări:

Pachetul DBMS_XMLGEN

La generarea unui document XML cu un astfel de pachet trebuie precizate unele informaţii (păstrate într-un context de generare), dintre care amintim: In continuare se vor descrie unele dintre funcţiile acestui pachet.
  1. In pachet există tipul de dată ctxType - care identifică un context unde se păstrează informaţiile necesare pentru generarea documentului XML.
  2. Pentru generarea unui astfel de context există două funcţii: La un astfel de context se pot asocia diverse informaţii, precizate în continuare.
    Generarea efectivă a documentului XML se face cu funcţia getXML().
  3. Denumirea elementului rădăcină din documentul XML astfel generat este implicit ROWSET, sau se poate preciza o altă denumire pentru elementul rădăcină prin procedura:
    setRowSetTag (ctx IN ctxHandle, rowSetTag IN VARCHAR2)
    Cu valoarea NULL se elimină extragerea acestui element în documentul XML.
  4. Denumirea implicită pentru tagul corespunzător liniilor este ROW. Această denumire se poate schimba prin procedura:
    setRowTag (ctx IN ctxHandle,rowTag IN VARCHAR2)
    Cu valoarea NULL se poate elimina apariţia acestui tag. Dacă valoarea este NULL şi există mai mult de o linie şi o coloană în rezultat, atunci va apare o eroare.
  5. In mod implicit denumirea tagurilor terminale (elementare), din documentul XML generat, este denumirea coloanelor din rezultatul execuţiei instrucţiunii SELECT. După documentaţie, această denumire se poate schimba prin adăugarea caracterelor _ITEM la denumirea coloanelor dacă se foloseşte procedura:
    useItemTagsForColl (ctx IN ctxHandle)
  6. Cu procedura
    setSkipRows (ctx IN ctxHandle,skipRows IN NUMBER) 
    se precizează numărul de înregistrări de la începutul rezultatului care nu sunt luate în considerare la generarea documentului XML.
  7. Cu procedura
    setMaxRows (ctx IN ctxHandle,maxRows IN NUMBER)
    se precizează numărul maxim de înregistrări prelucrate pentru generarea documentului XML.
  8. In documentul XML care se generează se poate face conversia caracterelor speciale (<, >, ", ') în echivalentul lor pentru XML (de exemplu "<" în "&lt;"). Această facilitate este precizată cu funcţia:
    setConvertSpecialChars (ctx IN ctxHandle, conv IN boolean)
    Valoarea TRUE pentru al doilea argument cere această conversie.
  9. Funcţia getXML() generează documentul XML. Se iau înregistrările rezultate din contextul de utilizare (toate înregistrările, cele rezultate prin folosirea funcţiilor setSkipRows, setMaxRows). Variantele de folosire sunt:

    Observaţii.

  10. Funcţia
    getNumRowsProcessed (ctx IN ctxHandle) RETURN NUMBER
    furnizează numărul de înregistrări folosite pentru a genera documentul XML.
  11. Pentru transformarea unui document XML de la o formă în care caracterele speciale se convertesc la echivalentul lor, respectiv pentru conversia inversă se poate folosi funcţia următoare, cu două variante de utilizare:
    convert (xmlData IN VARCHAR2, flag IN NUMBER := ENTITY_ENCODE) RETURN VARCHAR2
    convert (xmlData IN CLOB, flag IN NUMBER := ENTITY_ENCODE) RETURN CLOB
    Prima variantă (conversia caracterelor speciale) se foloseşte dacă al doilea argument lipseşte sau apare cu valoarea ENTITY_ENCODE
  12. La sfârşitul utilizării unui context este necesar ca el să fie închis:
    closeContext ( ctx IN ctxHandle)

Exemple

Următoarea procedură face afişarea pe ecran, în SQL*Plus sau SQL Developer, a unei date CLOB, divizată în subşiruri terminate cu caracterul chr(10) (funcţia se va folosi pentru a exemplifica generarea documentelor XML):
create or replace procedure ExtrageCLOB(v IN OUT NOCOPY CLOB) is
  s varchar2(32767);
  x varchar2(2000);
begin
  dbms_output.enable;
  s := dbms_lob.substr(v,32767);  
  -- din v (CLOB) extrage un subsir (de lungime maxima 32767) incepand cu prima pozitie
  -- pentru s (sir de caractere) se pot folosi functii mai multe
  loop
    exit when s is null;
    x := substr(s,1,instr(s,chr(10))-1);
    dbms_output.put_line(x);
    s := substr(s,instr(s,chr(10))+1);
  end loop;
end;

Generarea şi afişarea unui document XML generat cu acest pachet se poate vedea în următorul bloc PL/SQL:

set serveroutput on
declare
  c DBMS_XMLGEN.ctxType;
  r CLOB;
begin
  -- crearea unui context
  c := DBMS_XMLGEN.newContext('select cod,denumire from sectii order by cod');
  -- precizeaza denumirea tagului radacina
  DBMS_XMLGEN.setRowSetTag (c, 'FACULTATE');
  -- precizeaza denumirea tagului pentru o inregistrare
  DBMS_XMLGEN.setRowTag (c, 'SECTIE');
  -- determina documentul XML
  r := DBMS_XMLGEN.getXML(c);
  -- afisarea documentului
  ExtrageCLOB(r);
  -- inchiderea contextului
  DBMS_XMLGEN.closeContext(c); 
end;

Pachetul DBMS_XMLQuery

Modul de lucru este asemănător cu cel de la pachetul DBMS_XMLGEN, dar cu facilităti mai multe. Procedurile şi funcţiile din pachet sunt:
 newContext( sqlQuery IN VARCHAR2) RETURN ctxType;
 newContext( sqlQuery IN CLOB) RETURN ctxType;
 closeContext( ctxHdl IN ctxType);
 setRowsetTag(ctxHdl IN ctxType, tag IN VARCHAR2);
 setRowTag(ctxHdl IN ctxType, tag IN VARCHAR2);
 setErrorTag( ctxHdl IN ctxType, tag IN VARCHAR2);
 setRowIdAttrName( ctxHdl IN ctxType, attrName IN VARCHAR2);
 setRowIdAttrValue( ctxHdl IN ctxType, colName IN VARCHAR2);
 setCollIdAttrName( ctxHdl IN ctxType, attrName IN VARCHAR2);
 useNullAttributeIndicator( ctxHdl IN ctxType, flag IN BOOLEAN);
 useTypeForCollElemTag( ctxHdl IN ctxType, flag IN BOOLEAN := true);
 setTagCase( ctxHdl IN ctxType, tCase IN NUMBER);
 setDateFormat( ctxHdl IN ctxType, mask IN VARCHAR2);
 setMaxRows ( ctxHdl IN ctxType, rows IN NUMBER);
 setSkipRows( ctxHdl IN ctxType, rows IN NUMBER);
 setStylesheetHeader( ctxHdl IN ctxType, uri IN VARCHAR2, type IN VARCHAR2 := 'text/xsl');
 setXSLT(ctxHdl IN ctxType, uri IN VARCHAR2, ref IN VARCHAR2 := null);
 setXSLT(ctxHdl IN ctxType, stylesheet CLOB, ref IN VARCHAR2 := null);
 setXSLTParam( ctxHdl IN ctxType, name IN VARCHAR2, value IN VARCHAR2);
 removeXSLTParam( ctxHdl IN ctxType, name IN VARCHAR2);
 setBindValue( ctxHdl IN ctxType, bindName IN VARCHAR2, bindValue IN VARCHAR2);
 setMetaHeader( ctxHdl IN ctxType, header IN CLOB := null);
 setDataHeader( ctxHdl IN ctxType, header IN CLOB := null, tag IN VARCHAR2 := null);
 setEncodingTag( ctxHdl IN ctxType, enc IN VARCHAR2 := DB_ENCODING);
 setRaiseException( ctxHdl IN ctxType, flag IN BOOLEAN);
 setRaiseNoRowsException( ctxHdl IN ctxType, flag IN BOOLEAN);
 setSQLToXMLNameEscaping( ctxHdl IN ctxType, flag IN BOOLEAN := true);
 propagateOriginalException( c txHdl IN ctxType, flag IN BOOLEAN);
 getExceptionContent( ctxHdl IN ctxType, errNo OUT NUMBER, errMsg OUT VARCHAR2);
 getDTD(ctxHdl IN ctxType, withVer IN BOOLEAN := false) RETURN CLOB;
 getDTD(ctx IN ctxType, xDoc IN CLOB, withVer IN BOOLEAN := false);
 getNumRowsProcessed( ctx IN ctxType) RETURN NUMBER;
 getVersion();
 getXML(sqlQuery IN VARCHAR2, metaType IN NUMBER := NONE) RETURN CLOB;
 getXML(sqlQuery IN CLOB, metaType IN NUMBER := NONE) RETURN CLOB;
 getXML(ctxHdl IN ctxType, metaType IN NUMBER := NONE) RETURN CLOB;
 getXML(ctxHdl IN ctxType, xDoc IN CLOB, metaType IN NUMBER := NONE);

Exemplu:

set serveroutput on
declare
  c DBMS_XMLGEN.ctxType;
  r CLOB;
begin
  -- crearea unui context
  c := DBMS_XMLQuery.newContext('select * from sectii');
  -- precizeaza denumirea tagului radacina
  DBMS_XMLQuery.setRowSetTag (c, 'FACULTATE');
  -- precizeaza denumirea tagului pentru o inregistrare
  DBMS_XMLQuery.setRowTag (c, 'SECTIE');
  -- determina documentul XML
  r := DBMS_XMLQuery.getXML(c);
  -- afisarea documentului
  ExtrageCLOB(r);
  -- inchiderea contextului
  DBMS_XMLQuery.closeContext(c); 
end;

Alte pachete

DBMS_XMLDOM
DBMS_XMLPARSER
DBMS_XMLSAVE
DBMS_XMLSchema
DBMS_XSLPROCESSOR