Oracle XMLType et DTD composées…

Les DTD sont, sans doute avec raison, considérées comme l’ancienne génération d’outil de description des documents XML, avantageusement remplaçables par les schémas XML (XSD) ou autres Relax NG.

Pourtant, la simplicité de leur écriture (et lecture), le non support des espaces de nommage (namespaces), leur antériorité et leur inclusion dans la norme, en font encore un outil très utilisé dans de nombreuses situations de mise en œuvre du XML.

Une DTD peut être inclue dans un document XML, référencer un fichier externe ou un peu des deux, c’est ce dernier exemple que trouverez dans cet article, mise en œuvre avec un XMLType et Oracle 11.2

DTD et fichier XML

Pour commencer, nous allons créer une DTD simple. Celle-ci décrit une structure de fichier XML qui contient une seule balise arkzoyd vide laquelle contient un attribut nommé img; voici la DTD en question

!cat arkzoyd.dtd
<!ELEMENT arkzoyd EMPTY>
<!ATTLIST arkzoyd img CDATA #REQUIRED>

Voici un fichier XML qui s’appuie sur cette DTD. En outre, le fichier fait référence à des éléments externes, ici un fichier image. Nous avons utilisé la notion d’ENTITY dans la structure du message XML pour référencer cette image. La syntaxe ci-dessous référence donc à la fois des éléments de structure externe (la DTD) et des éléments de structure interne (l’ENTITY) qui font appel à des ressources externes ; voici le fichier XML :

<?xml version="1.0" encoding="UTF-8" standalone='yes'?>
<!DOCTYPE arkzoyd [
<!ENTITY % myDTD SYSTEM "/public/dtd/arkzoyd.dtd">
%myDTD;
<!NOTATION GIF SYSTEM "CompuServe Graphics Interchange Format 87a">
<!ENTITY TheArKZoYdCompany SYSTEM "http://arkzoyd.wpengine.com/_/rsrc/1329935439815/config/customLogo.gif?revision=10" NDATA GIF>
]>
<arkzoyd img="TheArKZoYdCompany"/>

Ce fichier est à la fois bien formé et valide comme vous pouvez vous en persuader à l’aide de XMLLINT :

xmllint arkzoyd.xml --valid
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE arkzoyd [
<!NOTATION GIF SYSTEM "CompuServe Graphics Interchange Format 87a" >
<!ENTITY % myDTD SYSTEM "/public/dtd/arkzoyd.dtd">
<!ELEMENT arkzoyd EMPTY>
<!ATTLIST arkzoyd img CDATA #REQUIRED>
<!ENTITY TheArKZoYdCompany SYSTEM "http://arkzoyd.wpengine.com/_/rsrc/1329935439815/config/customLogo.gif?revision=10" NDATA GIF>
]>
<arkzoyd img="TheArKZoYdCompany"/>

Enregistrer DTD et Fichier dans Oracle 11.2

Oracle 11.2 permet d’enregistrer la DTD dans XML Database à l’aide de la commande ci-dessous

create directory dtds as '/public/dtd';

set serveroutput on
declare
res boolean;
begin
res := dbms_xdb.createFolder('/public/dtd');
if (not res) then
dbms_output.put_line('error');
end if;
res := dbms_xdb.createResource('/public/dtd/arkzoyd.dtd',
bfilename('DTDS','arkzoyd.dtd'));
if (not res) then
dbms_output.put_line('error');
end if;
commit;
end;
/

select any_path
from resource_view
where any_path like '%/public/dtd/arkzoyd.dtd%';

ANY_PATH
-----------------------
/public/dtd/arkzoyd.dtd

Vous pourrez créer une table de type XMLType qui supporte l’utilisation des DTD (i.e. store as binary XML) :

create table ArKZoYd of xmltype xmltype store as binary xml                               
virtual columns (IMG AS (XMLCast(XMLQuery('/arkzoyd/@img'
PASSING OBJECT_VALUE RETURNING CONTENT) AS VARCHAR2(100))));

Le chargement du fichier se fait comme suit ; celui-ci est automatiquement validé par la base de données au moins en versions 11.2.0.2 et 11.2.0.3 :

create directory xmlfile as '/home/oracle/xml';

insert into ArKZoYd
values (xmltype(bfilename('XMLFILE','arkzoyd.xml'),
nls_charset_id('AL32UTF8')));
commit;
select img from ArKZoYd;

IMG
-----------------
TheArKZoYdCompany

Voilà !