Validating and XML File against DTD external file in PL/SQL Sept 20, 2008
I have spent sometime researching this subject until I finally came to an acceptable solution
In a previous tip, an example was given on how to read an XML.
In this tip, validating this XML against a DTD is explained
First of all, you need to create an XML file and give it a name, I called it test.dtd
Second, it is important to realize that DBMS_XMLParser package (as is the case with other Oracle packages) do not write and read file directly to/from the OS for security reasons.
This implies that we need to do some steps to store the test.dtd within the database. The approach here is to save it into the Oracle XML DB repository
To transfer the test.dtd to the repository we need to understand that Oracle XML DB repository allows you to transfer files into the Oracle database using FTP (!!!! YES there is an FTP server inside the Oracle database) :-
To test it run the following command
SQL>select DBMS_XDB.GETFTPPORT() from dual;
if the answer is zero, then you need to set the FTP port
SQL>call dbms_xdb.setFTPPORT(2100); -- setting the ftp port to 2100
SQL>alter system register;
To test is go to your DOS command prompt by using windows Start--> Run -->cmd
Here we are going to start an FTP session on port 2100 and connect to SCOTT
Type ftp
ftp>Open localhost 2100 -- assuming you are running a local Oracle instance on your machine
Connected to Ammar.
220- Ammar
Unauthorised use of this FTP server is prohibited and may be subject to civil an
d criminal prosecution.
220 Ammar FTP Server (Oracle XML DB/Oracle Database) ready.
User (Ammar:(none)):SCOTT
331 pass required for SCOTT
Password:
230 SCOTT logged in
Then check the contents by typing dir
ftp> dir
200 PORT Command successful
150 ASCII Data Connection
drw-r--r-- 2 SYS oracle 0 MAY 18 07:21 home
drw-r--r-- 2 SYS oracle 0 SEP 20 20:19 public
drw-r--r-- 2 SYS oracle 0 MAY 18 07:21 sys
-rw-r--r-- 1 SYS oracle 0 SEP 20 11:11 xdbconfig.xml
226 ASCII Transfer Complete
ftp: 250 bytes received in 0.00Seconds 250000.00Kbytes/sec.
now you can check what is inside the public directory by using the cd command and then dir
ftp>cd public
ftp>dir
Therefore you can use the put command to transfer the dtd file
however, there is another approach as well
SQL>declare
res boolean;
begin
res := dbms_xdb.createResource('/public/test.dtd',bfilename('XMLDIR','test.dtd'));
end;
/
commit;
XMLDIR is an Oracle directory pointing to where the dtd file is located and /public/ is the folder within XML DB repository where the DTD is going to reside
Next, you need to edit your XML and associate the XML file with DTD file using the highlighted line
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE college
SYSTEM "/public/test.dtd"> -- this line informs the parser to
validate againt the specified DTD
<college>
<master>
<id>10</id>
<name>ammar</name>
<row>
<student_id>1</student_id>
<student_name>Ahmad</student_name>
</row>
<row>
<student_id>2</student_id>
<student_name>Samia</student_name>
</row>
</master>
</college>
Note: The DTD is given at the end of the page
Run the example given in the Loading XML file tip without changes, this time the PL/SQL parser shall also validate against the DTD.
To summaries:
1) Create you DTD file
2) store the DTD in the XML DB repository
3) modify the XML file and add !DOCTYPE college SYSTEM "/public/test.dtd
<?xml encoding="UTF-8"?>
<!ELEMENT college (master)>
<!ATTLIST college
xmlns CDATA #FIXED ''>
<!ELEMENT master (id,name,row+)>
<!ATTLIST master
xmlns CDATA #FIXED ''>
<!ELEMENT id (#PCDATA)>
<!ATTLIST id
xmlns CDATA #FIXED ''>
<!ELEMENT name (#PCDATA)>
<!ATTLIST name
xmlns CDATA #FIXED ''>
<!ELEMENT row (student_id,student_name)>
<!ATTLIST row
xmlns CDATA #FIXED ''>
<!ELEMENT student_id (#PCDATA)>
<!ATTLIST student_id
xmlns CDATA #FIXED ''>
<!ELEMENT student_name (#PCDATA)>
<!ATTLIST student_name
xmlns CDATA #FIXED ''>