XML w Oracle9i
autor: leopold wegner

Coś o XML

Komponenty XML w Oracle9i

Typowe zastosowania komponentów XML w rozwiązaniach biznesowych

Oracle Development Tools

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.

 

Przechowywanie danych XML z Oracle9i

Wsparcie XML w bazie danych

Kiedy warto stosować poszególne podejścia przechowywania dokumentów 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

Komponenty XDK Języki  Opis

XML Parser 

Java, C, C++, PL/SQL 

Tworzy i parsuje XML używając interfejsów DOM lub SAX

XSLT Processor 

Java, C, C++, PL/SQL 

Transformuje XML w inny bazujący na tekscie format np. HTML lub WML 

XML Schema Processor 

Java, C, C++  

Pozwala używać prostych lub złożonych typów danych do opisu dokumentów XML przy użyciu XML Schema

XML Class Generator 

Java, C++ 

Automatycznie generuje klasy Java i C++ z DTD i XML Schema

XML Transviewer Java Bean 

Java 

Podgląd i transformacja dokumentów XML poprzez komponenty Javy

XML SQL Utility (XSU) 

Java, PL/SQL 

Generacja dokumentów XML, DTD i XML Schema z zapytań SQL

XSQL Servlet 

Java 

Połączenie XML, SQL, i XSLT na serwerze aby dostarczać dynamiczną zawartość stron Web-owych

Parsery XML

Oracle dostarcza  parsery XML dla Javy, C, C++ i PL/SQL. Każdy parser jest osobnym komponentem, który parsuje dokument XML tak aby mógł być przetwarzany przez aplikację. Parsery te wspierają:

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:

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:

 

  1. Użytkownik podaje URL poprzez przeglądarkę. URL jest interpretowany i przekazywany do XSQL Serwlet przez Java Web Server. URL zawiera nazwę docelowego pliku XSQL (.xsql) oraz opcjonalnie parametery, np. nazwa arkusza XSL (użytkownk może wywołać XSQL Serwleta z linii komend, pomijając przeglądarkę i Java web serwera).
  2. Serwlet przekazuje plik XSQL do parsera XML dla Javy, który parsuje XML i tworzy API dostępu do zawartości XML.
  3. Komponent serwletu (Page Processor) używa tego API do przekazania parametrów XML i poleceń SQL (w specjalnych tagach) do XML SQL Utility (XSU). Polecenia XSL do procesora XSLT.
  4. XML SQL Utility wysyła zapytania SQL do odpowiedniej bazy Oracle9i. Wyniki są zwracane XSU.
  5. XSU przesyła wyniki zapytania do procesora XSLT jako sformatowany tekst XML. Wyniki są osadzone w pliku XML w tym samym miejscu co oryginalne zapytanie (w tagach <query>).
  6. Jeżeli jest to potrzebne można wyniki zapytania przekształcić za pomocą procesora XSLT wg. wskazanego arkusza XSL. Procesor XSLT może selektywnie zastosować różne arkusze stylów opierając się na typie klienta, od którego pochodziło początkowe wywołałanie URL-a. Ta informacja (HTTP_USER_AGENT) jest uzyskiwana od klienta poprzez zapytanie HTTP.
  7. Procesor XSLT przekazuje gotowy dokument z powrotem do przeglądarki klienta.

 

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

<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

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>