28. Mai 2009

Tabellendaten als XML im Browser: einfach so!

English title: Accessing table data as XML with a browser - no coding required

Vor einiger Zeit hatte ich ja mal ein kleines Tutorial zum Thema XML erzeugen mit den SQL/XML-Funktionen veröffentlicht. Damit ist es möglich, Tabellendaten in beliebiger Art und Weise als XML aufzubereiten.
Some time ago I published a tutorial about generating XML using the SQL/XML functions. With this functions you can construct XML from table data. The functions are very powerful - you can construct any XML structure you want.
Aber wusstet Ihr schon, dass Ihr XML auch völlig ohne Code generieren könnt ...?
But did you know that you can generate simple XML without any coding ...?
Seit Oracle9i gibt es das DB URI Servlet und die DB URI Types. Und das lässt sich ganz einfach nutzen. Zuerst solltet Ihr prüfen, ob der HTTP-Listener eurer Datenbank aktiv ist. Das geschieht ganz einfach mit einem lsnrctl status.
Since Oracle9i there is the DBURI Servlet and the DBURI type. The usage of this is very simple. But beforehand you should check whether the HTTP listener of your database is actually running. This is done with lsnrctl status.
$ lsnrctl status
LSNRCTL for Linux: Version 11.1.0.7.0 - Production on 27-MAY-2009 19:57:37

Copyright (c) 1991, 2008, Oracle.  All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.2.140)(PORT=1521)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 11.1.0.7.0 - Production
Start Date                27-MAY-2009 19:49:19
Uptime                    0 days 0 hr. 8 min. 18 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /oracle/u01/app/oracle/product/11.1.0/network/admin/listener.ora
Listener Log File         /oracle/u01/app/oracle/diag/tnslsnr/vmware/listener/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.2.140)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=vmware.de.oracle.com)(PORT=8081))(Presentation=HTTP)(Session=RAW))
Services Summary...
Service "orcl.doag.org" has 1 instance(s).
  Instance "orcl", status READY, has 2 handler(s) for this service...
Service "orclXDB.doag.org" has 1 instance(s).
  Instance "orcl", status READY, has 3 handler(s) for this service...
Service "orcl_XPT.doag.org" has 1 instance(s).
  Instance "orcl", status READY, has 2 handler(s) for this service...
The command completed successfully
Wenn die rote Zeile bei euch nicht vorhanden ist, müsst Ihr den HTTP-Listener erst aktivieren. Das geht bei 11g-Datenbanken mit der Prozedur DBMS_XDB.SETHTTPPORT oder auch bei älteren Datenbanken mit dem SQL-Skript $ORACLE_HOME/rdbms/admin/catxdbdbca.sql. Nehmt einen TCP/IP-Port eurer Wahl; mit dem Port "0" wird der HTTP-Listener abgeschaltet.
If the red line is missing in your environment the HTTP listener is deactivated (which is the default). You can activate it with the procedure DBMS_XDB.SETHTTPPORT in Oracle11g and the $ORACLE_HOME/rdbms/admin/catxdbdbca.sql in older releases. Just choose an TCP/IP port; zero ("0") deactivates the listener.
Nun könnt Ihr Tabellendaten als XML abrufen. Startet einen Browser und gebt mal folgende URL ein, umdie Daten der EMP-Tabelle zu betrachten.
Now you can start viewing table data - start your browser and enter the following URL.
http://[database-host]:[http-port]/oradb/SCOTT/EMP
Ihr werdet zunächst aufgefordert, euch einzuloggen; nehmt einen Datenbankuser, der die Tabelle EMP lesen kann (naheliegenderweise SCOTT). Daraufhin solltet Ihr in etwa folgendes Ergebnis sehen.
First you get prompted for username and password. Enter the credentials of a user which is capable to select the EMP table (I'd suggest the SCOTT user). You should see the following result then.
Tabellendaten als XML - im Browser
Die XML-Struktur ist in diesem Fall vorgegeben; sie kann nicht beeinflusst werden. Aber im Gegenzug generiert die Datenbank ohne viel Aufwand XML aus den Tabellendaten. Wenn Ihr eigene XML-Strukturen benötigt, sind wir wieder bei den eingangs erwähnten SQL/XML-Funktionen. Und in manchen Fällen reicht diese einfache XML-Struktur vielleicht sogar aus ...
The structure of the XML document cannot be changed - it is always that simple. If you need other XML structures you have to code a view with the above mentioned SQL/XML functions. But there might be cases in which this simple structure is sufficient.
Ihr könnt die Ansicht auch mit Kriterien beschränken; dazu wird XPath-Syntax verwendet. Aber Achtung; das DB URI Servlet unterstützt nicht die komplette XPath-Syntax, nur ein Subset kann verwendet werden. Die XML-Funktionen in der Datenbank wie EXTRACTVALUE oder EXISTSNODE unterstützen XPath dagegen vollständig. So zeigt die folgende URL nur eine Zeile aus der EMP-Tabelle an.
You can apply filter criteria to the URI; use XPath notation for this. But keep in mind that this particular DBURI Servlet does not support 100% of XPath. The XML functions in the database(like EXISTSNODE or EXTRACTVALUE) at the other hand do fully support XPath.
http://[host]:[port]/oradb/SCOTT/EMP/ROW[EMPNO=7839]
Auch andere Kriterien sind möglich; wenn mehrere Zeilen selektiert werden, ist jedoch ein zusätzlicher Parameter rowsettag nötig, sonst gibt es eine Fehlermeldung.
Other criteria is also possible - but use the rowsettag parameter when you expect more then one row - an error is raised otherwise.
http://[host]:[port]/oradb/SCOTT/EMP/ROW[JOB="CLERK"]?rowsettag=QUERY
Mit der Funktion SYS_DBURIGEN könnt Ihr euch URLs generieren lassen. Damit wird es möglich, auf eine bestimmte Tabellenspalte in einer bestimmten Zeile mit genau einer Zeichenkette, eben der URI zu verweisen.
The SYS_DBURIGEN function allows to generate such URI. An URI is (expressed otherwise) a pointer to a single value in the database - as the following example illustrates.
SQL> select sys_dburigen(ENAME, SAL) from partner.emp where empno=7844;

SYS_DBURIGEN(ENAME,SAL)(URL, SPARE)
--------------------------------------------------------------------------------
DBURITYPE('/PARTNER/EMP/ROW[ENAME=''TURNER'']/SAL', NULL)
Setzt man nun Hostname und Port und das Schlüsselwort oradb davor, so kann man sich das Ergebnis im Browser ansehen ... aber auch in SQL können diese URI verwendet werden. Dazu gibt es den Objekttypen DBURITYPE.
Prefix this with the hostname, the TCP/IP-Port of the HTTP listener and the oradb keyword and you can (again) bnavigate to this value with the browser. But the DBURIs can also be used in SQL queries - the DBURITYPE object type is there for this.
SQL> select dburitype('/PARTNER/EMP/ROW[ENAME=''TURNER'']/SAL').getxml() from dual;

DBURITYPE('/PARTNER/EMP/ROW[ENAME=''TURNER'']/SAL').GETXML()
--------------------------------------------------------------------------------
<?xml version="1.0"?>
<SAL>1501</SAL>
Probiert es mal aus ... insbesondere die Variante über den Browser kann sehr interessant sein. Wenn man nun noch berücksichtigt, dass Kommandozeilenwerkzeugen wie wget es erlauben, diese Funktionalität in Batchläufen zu nutzen, dann wird es sehr einfach, XML von der Datenbank in andere Systeme zu übertragen. Einfacher geht es nun wirklich nicht ...
Give it a try. The simple browser access might be of particluar interest if you need to provide XML data from the database in a short timeframe. Consider the wget commandline utility which allows to use this feature in batch processes. Transferring XML data between the database and other systems is then a very simple task.
Mehr Informationen zu den DB URIs findet Ihr im XML DB Handbuch. Darin enthalten sind auch Informationen über zusätzliche HTTP-Parameter, die Ihr verwenden könnt - so kann transform eine XSLT-Transformation auslösen ... schaut einfach mal rein.
More information is contained in the XML DB documentation. This also contains additional parameters which can be applied to the HTTP URL's (e.g. transform for Stylesheet (XSLT)-transformations).

Beliebte Postings