XML w Oracle9i
autor: leopold wegner
Coś o XML
XML (eXtensible Markup Language) standard opracowany przez W3C
standard opisu strukturalnych danych
odzielenie danych od struktury i prezentacji (do opisu prezentacji służy XSL (eXtensible Stylesheet Language)
Komponenty XML w Oracle9i
XMLType- nowy typ danych do przechowywania dokumentów XML, obsługa zapytańSYS_XMLGEN- funkcja SQL do tworzenia dokumnetów XMLSYS_XMLAGG- funkcja SQL do łączenia wielu dokumentów XMLDBMS_XMLGEN- wbudowany pakiet do tworzenia dokumnetów XML z zapytań SQL- wsparcie URI - przechowywanie i odzyskiwanie globalnych i wewnątrz bazodanowych referencji
 - wsparcie Oracle Text (interMedia Text) - wsparcie XPath dla
 XMLTypei kolumn tekstowych
- XML Parser for Java and XSLT Processor
 - XML Schema Processor for Java
 - XML Class Generator for Java
 - XSQL Servlet and Pages
 - XML SQL Utility (XSU) for Java
 
- XML Transviewer Beans
 
- DOMBuilder Bean
 - XSLTransformer Bean
 - DBAccessBean
 - TreeViewer Bean
 - SourceViewer Bean
 - XMLTransformPanel Bean
 - DBViewer Bean
 
- XML Parser for C
 - XML Schema Processor for C
 
- XML Parser for C++
 - XML Schema Processor for C++
 - XML Class Generator for C++
 
- XML Parser for PL/SQL
 - XML SQL Utility (XSU) for PL/SQL
 
Typowe zastosowania komponentów XML w rozwiązaniach biznesowych

XSQL Servlet and Pages, Oracle9i Internet File System (9iFS), JDeveloper, Business Components for Java (BC4J), Oracle Portal (WebDB), Oracle9iAS Reports Services, and Oracle9i Dynamic Services - kolejne komponenty mogące się przydać podaczas tworznia aplikacji XML-owej.
CONTAINS i WITHIN)
  XMLType
    (implementacja poprzez CLOB - Character Large Object)
    lub też po prostu kolumny CLOB/BLOB; wykorzystanie w przypadku XMLType
    funkcji Extract() i ExistsNode()
    lub indeksowania Oracle Text do przeszukiwania takich dokumentówXMLType
    XMLType przechowuje dokumenty XML
    jako Character Large Objects (CLOBs). Indeksowanie Oracle Text (interMedia
    Text) może być użyte do obsługi kolumny XMLType, a 
    także zapytań wykorzystujących operator CONTAINS lub
    Xpath-podobnej składni. Typ XMLType posiada wiele funkcji, które
    mogą zostać użyte do pracy z fragmentami dokumentu XML.

Kiedy będzie potrzeba wyciągnięcia danych z bazy, korzystamy z perspektywy, która bazując na różnych kawałkach danych zwróci posklejany wynik. Następnie XML SQL Utility stworzy całościowy dokument XML.
Coś na temat komponentów
Działanie parsera XML dla Javy

Przykładowe zastosowanie parsera XML i DOM (dla Javy)
// This file demonstates a simple use of the parser and DOM API.
// The XML file given to the application is parsed.
// The elements and attributes in the document are printed.
// This demonstrates setting the parser options.
//
import java.io.*;
import java.net.*;
import org.w3c.dom.*;
import org.w3c.dom.Node;
import oracle.xml.parser.v2.*;
public class DOMSample
{
   static public void main(String[] argv)
   {
      try
      {
         if (argv.length != 1) 
         {
            // Must pass in the name of the XML file.
            System.err.println("Usage: java DOMSample filename");
            System.exit(1);
         }
         // Get an instance of the parser
         DOMParser parser = new DOMParser();
	 // Generate a URL from the filename.
	 URL url = createURL(argv[0]);
         // Set various parser options: validation on,
         // warnings shown, error stream set to stderr.
         parser.setErrorStream(System.err);
         parser.setValidationMode(DTD_validation);
         parser.showWarnings(true);
	 // Parse the document.
         parser.parse(url);
         // Obtain the document.
         XMLDocument doc = parser.getDocument();
         // Print document elements
         System.out.print("The elements are: ");
         printElements(doc);
         // Print document element attributes
         System.out.println("The attributes of each element are: ");
         printElementAttributes(doc);
         parser.reset();
      }
      catch (Exception e)
      {
         System.out.println(e.toString());
      }
   }
   static void printElements(Document doc)
   {
      NodeList nl = doc.getElementsByTagName("*");
      Node n;
         
      for (int i=0; i<nl.getLength(); i++)
      {
         n = nl.item(i);
         System.out.print(n.getNodeName() + " ");
      }
      System.out.println();
   }
   static void printElementAttributes(Document doc)
   {
      NodeList nl = doc.getElementsByTagName("*");
      Element e;
      Node n;
      NamedNodeMap nnm;
      String attrname;
      String attrval;
      int i, len;
      len = nl.getLength();
      for (int j=0; j < len; j++)
      {
         e = (Element)nl.item(j);
         System.out.println(e.getTagName() + ":");
         nnm = e.getAttributes();
         if (nnm != null)
         {
            for (i=0; i<nnm.getLength(); i++)
            {
               n = nnm.item(i);
               attrname = n.getNodeName();
               attrval = n.getNodeValue();
               System.out.print(" " + attrname + " = " + attrval);
            }
         }
         System.out.println();
      }
   }
   static URL createURL(String fileName)
   {
      URL url = null;
      try 
      {
         url = new URL(fileName);
      } 
      catch (MalformedURLException ex) 
      {
         File f = new File(fileName);
         try 
         {
            String path = f.getAbsolutePath();
            String fs = System.getProperty("file.separator");
            if (fs.length() == 1)
            {
               char sep = fs.charAt(0);
               if (sep != '/')
                  path = path.replace(sep, '/');
               if (path.charAt(0) != '/')
                  path = '/' + path;
            }
            path = "file://" + path;
            url = new URL(path);
         } 
         catch (MalformedURLException e) 
         {
            System.out.println("Cannot create url for: " + fileName);
            System.exit(0);
         }
      }
      return url;
   }
}
    
XML Class Generator
XML Class Generator tworzy zbiór klas Java lub C++ na podstawie dokumentów DTD, XML Schema.

XML Transviewer Java Beans
XML Transviewer Beans to zbiór komponentów XML dla aplikacji i apletów Javy. Służą do przekształacania i przeglądania danych i dokumentów XML. Komponenty mogą być zintegrowane z Oracle JDeveloper.
zawiera Java XML Parser razem z bean interfejsem (rozszerzona funkcjonalność umożliwiając parsowanie asynchroniczne). Aplikacja w Javie może parsować kolejno wiele dokumentów zwracając natychmiast sygnały kontrole wywołującemu.
ułatwia przeglądanie plików XML i XSL (kolorowanie składni). Łatwo zintegrować z DOM Builder Bean, co umożliwia pre i post parsowanie oraz sprawdzanie poprawności względem danego DTD.
wizualizuje drzewo opisujšce dokument XML, umożliwiając wygodne przeglądanie (zwijanie gałęzi) i modyfikowanie tego drzewa
umożliwia translację dokumentu XML do innych formatów, np. HTML, DDL, poprzez zastosowanie szablonu styli XSL. W połączniu z innymi komponentami, XSL TB pozwala aplikacji lub użytkownikowi na natychmiastowe skontrolowanie wyniku tłumaczenia. Inne zastosowanie - w aplikacji po stronie serwera albo w serwlecie do przekształcania dokumentu XML (np. wynik zapytania) w HTML (wyświetlenie przez przeglądarkę).
Ten komponent używa innch ziaren do tworzenia przykładowych aplikacji, które mogą przetwarzać pliki XML. Zapewnia interfejs do ładowania dokumentów XML i XSL. Używa:
- Visual beans do przeglądania i edycji plików
 - Transformer bean do zastosowania arkuszy stylów do dokumentu XML (podgląd wyniku)
 
XML SQL Utility (XSU)
XML SQL Utility - klasy Javy do automatycznego i dynamicznego przetwarzania wyników zapytań SQL w dokumenty XML. Mogą być używane do:Struktura wynikowego dokumentu XML jest oparta na wewnętrznej strukturze schematu bazy danych (którego dotyczyło zapytanie).
Przykładowy wynik działania XSU:
CREATE TYPE AddressType AS OBJECT ( 
 STREET VARCHAR2(20),
 CITY VARCHAR2(20), 
 STATE CHAR(2), 
 ZIP VARCHAR2(10) 
);
CREATE TYPE EmployeeType AS OBJECT ( EMPNO NUMBER, ENAME VARCHAR2(20), SALARY NUMBER, EMPADDR AddressType );
CREATE TYPE EmployeeListType AS TABLE OF EmployeeType;
CREATE TABLE dept ( DEPTNO NUMBER, DEPTNAME VARCHAR2(20), DEPTADDR AddressType, EMPLIST EmployeeListType ) NESTED TABLE EMPLIST STORE AS EMPLIST_TABLE;
<?xml version='1.0'?> 
<ROWSET> 
 <ROW num="1"> 
  <DEPTNO>100</DEPTNO> 
  <DEPTNAME>Sports</DEPTNAME> 
  <DEPTADDR> 
   <STREET>100 Redwood Shores Pkwy</STREET> 
   <CITY>Redwood Shores</CITY> 
   <STATE>CA</STATE> 
   <ZIP>94065</ZIP> 
  </DEPTADDR> 
  <EMPLIST> 
   <EMPLIST_ITEM num="1"> 
    <EMPNO>7369</EMPNO> 
    <ENAME>John</ENAME> 
    <SALARY>10000</SALARY> 
    <EMPADDR> 
     <STREET>300 Embarcadero</STREET> 
     <CITY>Palo Alto</CITY> 
     <STATE>CA</STATE> 
     <ZIP>94056</ZIP> 
    </EMPADDR> 
   </EMPLIST_ITEM> 
   <!-- additional employee types within the employee list --> 
  </EMPLIST> 
 </ROW> 
 <!-- additional rows ... --> 
</ROWSET>
Przykład kody Javy:
Import oracle.jdbc.driver.*;
import oracle.xml.sql.query.OracleXMLQuery;
import java.lang.*;
import java.sql.*;
// class to test the String generation!
class testXMLSQL {
   public static void main(String[] argv)
   {
     try{
      // create the connection
      Connection conn  = getConnection("scott","tiger");
      // Create the query class.
      OracleXMLQuery qry = new OracleXMLQuery(conn, "select * from emp");
      // Get the XML string
      String str = qry.getXMLString();
      // Print the XML output
      System.out.println(" The XML output is:\n"+str);
      // Always close the query to get rid of any resources..
     qry.close();
     }catch(SQLException e){
      System.out.println(e.toString());
     }
   }
   // Get the connection given the user name and password..!
   private static Connection getConnection(String username, String password)
     throws SQLException
   {
      // register the JDBC driver..
       DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
      // Create the connection using the OCI8 driver
       Connection conn =
        DriverManager.getConnection("jdbc:oracle:oci8:@",username,password);
      return conn;
   }
}
XSQL Page Processor and Servlet
The XSQL Page Processor and Servlet - narzędzie do przetwarzania zapytań SQL i zwracania rezultatów w postaci XML, zaimplementowane jako serwlet Javy. Zastosowanie: dostarczanie dynamicznej zawartości stron internetowych. Na wejściu dostaje plik XML zawierający zapytania SQL. Korzysta z parsera XML i XSU oraz XLST. Można uruchomić ten serwlet na każdym serwerze webowym, który wspiera serwlety Javy.
XSQL Page Processor and Servlet w działaniu:

Przykładowe użycie XDK
Generacja dokumentów XML używająć XDK dla Java

Generacja dokumentów XML używająć XDK dla C++ (dla C bez Class generatora)

Generacja dokumentów XML używająć XDK dla PL/SQL

TYP XMLType
proste przykłądy z użyciem XMLType
    
CREATE TABLE warehouses(
warehouse_id NUMBER(3),
warehouse_spec SYS.XMLTYPE,
warehouse_name VARCHAR2(35),
location_id NUMBER(4));
INSERT into warehouses (warehouse_id, warehouse_spec) VALUES (1001, sys.XMLType.createXML( '<Warehouse whNo="100"> <Building>Owned</Building> </Warehouse>'));
SELECT w.warehouse_spec.extract('/Warehouse/Building/text()').getStringVal()
"Building"
FROM warehouses w
Building
-----------------
Owned
UPDATE warehouses SET warehouse_spec = sys.XMLType.createXML('<Warehouse whono="200"> <Building>Leased</Building></Warehouse>'));
DELETE FROM warehouses e WHERE e.warehouse_spec.extract('//Building/text()').getStringVal() = 'Leased';
CREATE TABLE po_xml_tab(
poid number,
poDoc SYS.XMLTYPE);
ALTER TABLE po_xml_tab add (custDoc sys.XMLType); ALTER TABLE po_xml_tab drop (custDoc sys.XMLType);CREATE TABLE po_xml_tab( poid NUMBER(10), poDoc SYS.XMLTYPE ) XMLType COLUMN poDoc STORE AS CLOB ( TABLESPACE lob_seg_ts STORAGE (INITIAL 4096 NEXT 4096) CHUNK 4096 NOCACHE LOGGING );
przykłądy zapytań
<PO>
<PONO>100</PONO>
<PNAME>Po_1</PNAME>
<CUSTOMER CUSTNAME="John"/>
<SHIPADDR>
<STREET>1033, Main Street</STREET>
<CITY>Sunnyvalue</CITY>
<STATE>CA</STATE>
</SHIPADDR>
</PO>
Kilka konstrukcji używanych w XPath
"/" oznacza korzeń drzewa wyżenia XPath np. /PO odpowiada dziecku korzenia o nazwie "PO"
"/" oznacza również separator do identyfikacji dzieci poszczególnych węzłów np. /PO/PNAME
"//" oznacza wszystkich potomków aktualnego węzła np. PO//ZIP odpowiada każdemu elementowi zip, który jest pod elementem o nazwie "PO"
"*" oznacza dowolny węzeł np. /PO/*/STREET odpowiada każdemu elementowi STREET, który jest wnukiem elementu o nazwie "PO"
INSERT INTO po_xml_tab values (100, sys.xmltype.createxml('<?xml version="1.0"?> <PO> <PONO>221</PONO> <PNAME>PO_2</PNAME> </PO>')); INSERT INTO po_xml_tab values (200, sys.xmltype.createxml('<?xml version="1.0"?> <PO> <PONAME>PO_1</PONAME> </PO>')); SELECT e.poDoc.extract('//PONO/text()').getNumberVal() as pono FROM po_xml_tab e WHERE e.podoc.existsnode('/PO/PONO') = 1 AND e.poid > 1; declare poxml SYS.XMLType; cust SYS.XMLType; val VARCHAR2; begin -- select the adt instance select poDoc into poxml from po_xml_tab p where p.poid = 100; -- do some traversals and print the output cust := poxml.extract('//SHIPADDR'); -- do something with the customer XML fragment val := cust.getStringVal(); dbms_output.put_line(' The customer XML value is '|| val); end;
CREATE TABLE cust_tab ( custid number primary key, custname varchar2(20) ); insert into cust_tab values (1001, "John Nike"); CREATE table po_rel_tab ( pono number, pname varchar2(100), custid number refernces cust_tab shipstreet varchar2(100), shipcity varchar2(30), shipzip varchar2(20) ); <?xml version = '1.0'?> <PO> <PONO>2001</PONO> <CUSTOMER CUSTNAME="John Nike"/> <SHIPADDR> <STREET>323 College Drive</STREET> <CITY>Edison</CITY> <STATE>NJ</STATE> <ZIP>08820</ZIP> </SHIPADDR> </PO> insert into po_rel_tab as select p.poDoc.extract('/PO/PONO/text()').getnumberval(), p.poDoc.extract('/PO/PNAME/text()').getstringval(), -- get the customer id corresponding to the customer name ( SELECT custid FROM cust_tab c WHERE c.custname = p.poDoc.extract('/PO/CUSTOMER/@CUSTNAME').getstringval() ), p.poDoc.extract('/PO/SHIPADDR/STREET/text()').getstringval(), p.poDoc.extract('//CITY/text()').getstringval(), p.poDoc.extract('//ZIP/text()').getstringval(), from po_xml_tab p;PONO PNAME CUSTID SHIPSTREET SHIPCITY SHIPZIP ---------------------------------------------------------------- 2001 1001 323 College Drive Edison 08820
przykłąd zastosowania DBMS_XMLGEN
CREATE TABLE new_departments ( department_id NUMBER PRIMARY KEY, department_name VARCHAR2(20) ); CREATE TABLE new_employees ( employee_id NUMBER PRIMARY KEY, last_name VARCHAR2(20), department_id NUMBER REFERENCES departments ); CREATE TYPE emp_t AS OBJECT( "@employee_id" NUMBER, last_name VARCHAR2(20) ); CREATE TYPE emplist_t AS TABLE OF emp_t; CREATE TYPE dept_t AS OBJECT( "@department_id" NUMBER, department_name VARCHAR2(20), emplist emplist_t ); qryCtx := dbms_xmlgen.newContext ('SELECT dept_t(department_id, department_name, CAST(MULTISET (SELECT e.employee_id, e.last_name FROM employees e WHERE e.department_id = d.department_id) AS emplist_t)) AS deptxml FROM departments d'); DBMS_XMLGEN.setRowTag(qryCtx, NULL);<ROWSET> <DEPTXML DEPARTMENT_ID="10"> <DEPARTMENT_NAME>SALES</DEPARTMENT_NAME> <EMPLIST> <EMP_T EMPLOYEE_ID="30"> <LAST_NAME>Scott</LAST_NAME> </EMP_T> <EMP_T EMPLOYEE_ID="31"> <LAST_NAME>Mary</LAST_NAME> </EMP_T> </EMPLIST> </DEPTXML> <DEPTXML DEPARTMENT_ID="20"> ... </ROWSET>