Skip to Main Content
  • Questions
  • Having problems while validating XML doc in Database based on XSD doc.

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Arvind.

Asked: June 27, 2003 - 10:45 am UTC

Last updated: March 23, 2006 - 1:56 pm UTC

Version: 9.2.0

Viewed 10K+ times! This question is

You Asked

Hi Tom,
After 2 months at last I got the chance to ask my question. Question is about Xml validation based on XSD schema definition:

Both documents are stored in different tables in XMLType fields.
I have a trigger on table valid_xml_schemas that fires whenever I update the VXS_SCHEMA field in table. I validate all the XML documents in the subset_family_details table which are having foreign key value pointing to the schema that I am updating in table valid_xml_schemas.

My problem is that if I take the :new.vxs_schema value and insert it into a temporary table and use the inserted value to validate the XML documents then it works and validates the documents for a valid schema but if instead of inserting into temporary table, I validate the XML documents against :new.vxs_schema then it fails the validation.

Here in this case you might have seen that schema is same with the difference of only populating from database and direct in coming value. Is it changing the value somewhere in between or we can not use any value other than database XSD value to validate the XML document ?

Codes:
-- stores XSD documents
PROMPT Creating Table 'VALID_XML_SCHEMAS'
CREATE TABLE VALID_XML_SCHEMAS
(VXS_ID NUMBER(4) NOT NULL
,VXS_NAME VARCHAR2(30) NOT NULL
,VXS_DESCRIPTION VARCHAR2(255)
,VXS_SCHEMA XMLTYPE NOT NULL
,VXS_PROG_ALIAS VARCHAR2(30) NOT NULL
,VXS_DISPLAY_SEQUENCE NUMBER(3) NOT NULL
,VXS_STATUS VARCHAR2(1) DEFAULT 'Y' NOT NULL
,VXS_STATUS_DATE DATE NOT NULL
,VXS_USER_CREATED VARCHAR2(30) NOT NULL
,VXS_DATE_CREATED DATE NOT NULL
,VXS_USER_MODIFIED VARCHAR2(30)
,VXS_DATE_MODIFIED DATE
)
/
-- stores XML documents
PROMPT Creating Table 'SUBSET_FAMILY_DETAILS'
CREATE TABLE SUBSET_FAMILY_DETAILS
(SFD_ID NUMBER(9) NOT NULL
,VSF_ID NUMBER(4) NOT NULL
,VXS_ID NUMBER(4) NOT NULL
,SFD_XML_DOC XMLTYPE NOT NULL
,SFD_USER_CREATED VARCHAR2(30) NOT NULL
,SFD_DATE_CREATED DATE NOT NULL
,SFD_USER_MODIFIED VARCHAR2(30)
,SFD_DATE_MODIFIED DATE
)
/

CREATE TABLE TEST( XSD XMLTYPE);

Java code:

package oracle.util;

import oracle.xml.parser.schema.XSDBuilder;
import oracle.xml.parser.schema.XMLSchema;
import oracle.xml.parser.v2.DOMParser;
import oracle.xml.parser.v2.XMLParser;
import oracle.xml.parser.v2.XMLParseException;
import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.sql.SQLException;
import java.io.IOException;
import oracle.sql.CLOB;

public class SchemaUtil{
public static String validation( CLOB xmlClob, CLOB xsdClob)throws Exception{
StringWriter sw = new StringWriter();
try
{
//Build Schema Object
String xml = getStringForClob(xmlClob);
String xsd = getStringForClob(xsdClob);
XSDBuilder builder = new XSDBuilder();
byte [] docbytes = xsd.getBytes();
ByteArrayInputStream in = new ByteArrayInputStream(docbytes);
XMLSchema schemadoc = (XMLSchema)builder.build(in,null);

//Parse the input XML document with Schema Validation
docbytes = xml.getBytes();

in = new ByteArrayInputStream(docbytes);
DOMParser dp = new DOMParser();

// Set Schema Object for Validation
dp.setXMLSchema(schemadoc);
dp.setValidationMode(XMLParser.SCHEMA_VALIDATION);

dp.setPreserveWhitespace (true);

dp.setErrorStream (new PrintWriter(sw));
dp.parse (in);

sw.write("WELLFORMED");
}
catch (XMLParseException pe)
{
sw.write("Parser Exception: " + pe.getMessage());
}
catch (Exception e)
{
sw.write("NonParserException: " + e.getMessage());
}
return sw.toString();
}

public static String getStringForClob(CLOB xmlObj) throws SQLException, IOException{
Reader clobStream = xmlObj.getCharacterStream ();
StringBuffer suggestions = new StringBuffer();
int nchars = 0;
char[] buffer = new char[1000];
while((nchars = clobStream.read(buffer)) != -1)
suggestions.append(buffer, 0, nchars);
clobStream.close();
return suggestions.toString();
}
}

Note: please create a Jar file for above class and load in database using( I know you know this but still I am wrinting :) ):

loadjava -resolve -verbose -user user/pwd@connectstring filename.jar



CREATE OR REPLACE PROCEDURE TEST_P(XSD XMLTYPE) IS
PRAGMA autonomous_transaction;
BEGIN
DELETE FROM TEST;
INSERT INTO TEST VALUES(XSD);
COMMIT;
END TEST_P;



CREATE OR REPLACE function schemavalidation(xml in clob, xsd in clob)
return varchar2
as language java name
'oracle.util.SchemaUtil.validation(oracle.sql.CLOB,oracle.sql.CLOB) returns java.lang.String';



CREATE OR REPLACE TRIGGER PQDTVXS
BEFORE UPDATE OF VXS_SCHEMA
ON VALID_XML_SCHEMAS
FOR EACH ROW
DECLARE
XML_not_wellformed Exception;
newline varchar2(1) := chr(10);
lv_out varchar2(32000);
lv_vxs_schemas Clob;
lv_vxs_id valid_xml_schemas.vxs_id%type;
lv_sfd_xml_doc Clob;

Type tp_clob is table of clob index by binary_integer;
sfd_xml_doc_tab tp_clob;

Cursor cur_xml_doc(in_vxs_id in valid_xml_schemas.vxs_id%type) is
select sfd.SFD_XML_DOC.getClobVal()
from subset_family_details sfd
where vxs_id = in_vxs_id;
BEGIN
-- case1: works:
TEST_P(:new.VXS_SCHEMA); -- works
SELECT X.XSD.getClobVal() INTO lv_vxs_schemas FROM TEST X;

-- case2 does not work...
--lv_vxs_schemas := :new.VXS_SCHEMA.getClobVal();

open cur_xml_doc(:new.vxs_id);
fetch cur_xml_doc bulk collect into sfd_xml_doc_tab;
if (sfd_xml_doc_tab.count > 0) then
for indx in sfd_xml_doc_tab.first..sfd_xml_doc_tab.last loop
lv_sfd_xml_doc := sfd_xml_doc_tab(indx);
lv_out := SchemaValidation(lv_sfd_xml_doc, lv_vxs_schemas);
lv_out := replace(lv_out,newline,'');
if ( substr(lv_out,1,1) != newline ) then
if ( substr(lv_out,1,10) != 'WELLFORMED') THEN
raise XML_not_wellformed;
end if;
else
raise XML_not_wellformed;
end if;
end loop;
end if;
EXCEPTION
WHEN XML_not_wellformed then
RAISE_APPLICATION_ERROR(-20010,'New Xsd document does not validate existing XML documents...'
||'delete XML documents first and then insert/update XSD again');

WHEN OTHERS THEN
RAISE;
END pqdtvxs;



Please let me know if you need any other information. Any help is appreciated.

Thanks,
Arvind K Sharma

and Tom said...

I asked Sean Dillon, our local XML Technologist, to take a look at this and here's what he had to say...
--

Hi Arvind,

Just so you know, Well-formedness is different from VALID XML according to an XML Schema. If you simply need to check for well-formed XML Schemas, you're already doing that by using the XMLType datatype. XMLType values can't be instantiated unless they are well-formed.

I tried reproducing your problem and couldn't boil it down to a test case that BROKE :-). I used some of the code on OTN for doing PLSQL-based XML Schema validation, and then added a trigger much the same as your above... and it worked fine. Here's what I came up with:

(all my source files are here: </code> http://asktom.oracle.com/~sdillon/asktom/plsqlschema/ <code>

@DBSchema.sql
@DBData.sql
loadjava -resolve -verbose -user sdillon/sdillon SchemaUtil.class
@SchemaUtil.sql
@printbuffer.sql
@dbvalid.sql

-- trig.sql:
create or replace trigger schema_tab_bifer
before update
on schema_tab
for each row
declare
l_out varchar2(4000);
begin
for i in (select xml from xml_tab) loop
l_out := schemavalidation(xmltype.extract(i.xml,'/').getStringVal(),
xmltype.extract(:new.xsd,'/').getStringVal());
printbufferout(l_out);
end loop;
end schema_tab_bifer;
/
show errors

-- test.sql:
@test.sql

SQL> update schema_tab
2 set xsd = xsd
3 /

| The input XML parsed without errors.
|
| <Line 1, Column 211>: XSD-2023: (Error) Invalid value of attribute: '1999-11-31'
| <Line 20, Column 18>: XSD-2105: (Error) Identity constraint validation error: 'Key sequence not found in key reference
'
| | Parser Exception: Invalid value of attribute: '1999-11-31'

1 row updated.

What this shows me is that the trigger fired and executed the XML Schema validation... I never had to insert the value into a temporary table and it works fine:

l_out := schemavalidation(xmltype.extract(i.xml,'/').getStringVal(),
xmltype.extract(:new.xsd,'/').getStringVal());

If you can create a slimmed down reproduceable test case I'd be more than happy to take a look at why it's not working. Hope that helps.

Rating

  (14 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

xmlType.toObject doesnt work

Oleg Oleander, October 02, 2003 - 8:38 am UTC

Dear Sean,

I have a nice and well working SQL object hierarchy in my DB, and I want to expose it thru XML to the client. I registered an XMLSchema and created XML-type views, and those work well. However I need to convert the schema-validated XML I got back from the client to SQL object in stored proc. to perform some actions, but I always got this internal error. 
Q1: Could you please tell me the cause of this internal error, and a passible workaround. 

My SQL object has an object hierarchy. I could register a schema that represents this extension of properties, but I would like to have a single view and a single table under it to present and store all descendant object of the root object. 
Q2: Could you please tell me, that is it feasable and how to do it?

for Q1:
SQL> create or replace type emp_t as object (
  2          empno number(4),
  3          ename varchar2(10),
  4          job   varchar2(9),
  5          mgr   number(4),
  6          hiredate date,
  7          sal   number(7,2),
  8          comm  number(7,2)
  9  );
 10  /

A típus létrejött.

SQL> 
SQL> create or replace type emplist_t as table of emp_t;
  2  /

A típus létrejött.

SQL> 
SQL> create or replace type dept_t as object (
  2          deptno number(2),
  3          dname  varchar2(14),
  4          loc    varchar2(13),
  5          emps   emplist_t
  6  ) not final;
  7  /

A típus létrejött.

SQL> 
SQL> declare
  2           xsd xmlType := xmlType(
  3  ' <schema targetNamespace="
http://www.oracle.com/dept.xsd"
 '||
  4  '               xmlns:my="
http://www.oracle.com/dept.xsd"
 '||
  5  '               xmlns="
http://www.w3.org/2001/XMLSchema"
 '||
  6  '               xmlns:xdb="
http://xmlns.oracle.com/xdb"
'||
  7  '               elementFormDefault="qualified" > '||
  8  '    <element name="DEPT_T" type="my:DEPT_TType" xdb:SQLSchema="XT" xdb:SQLType="DEPT_T" xdb:defaultTable="DEPARTMENT"/> '||
  9  '    <complexType name="DEPT_TType"> '||
 10  '     <sequence> '||
 11  '      <element name="DEPTNO" type="double" xdb:SQLName="DEPTNO" xdb:SQLType="NUMBER"/> '||
 12  '      <element name="DNAME" type="string" xdb:SQLName="DNAME" xdb:SQLType="VARCHAR2"/> '||
 13  '      <element name="LOC" type="string" xdb:SQLName="LOC" xdb:SQLType="VARCHAR2"/> '||
 14  '      <element name="EMPS" type="my:EMPS_Type" maxOccurs="unbounded" minOccurs="0" xdb:SQLName="EMPS" xdb:SQLType="EMP_T" xdb:SQLCollType="EMPLIST_T" xdb:SQLSchema="XT" /> '||
 15  '     </sequence> '||
 16  '    </complexType> '||
 17  '    <complexType name="EMPS_Type"> '||
 18  '     <sequence> '||
 19  '      <element name="EMPNO" type="double" xdb:SQLName="EMPNO" xdb:SQLType="NUMBER"/> '||
 20  '      <element name="ENAME" type="string" xdb:SQLName="ENAME" xdb:SQLType="VARCHAR2"/> '||
 21  '      <element name="JOB" type="string" xdb:SQLName="JOB" xdb:SQLType="VARCHAR2"/> '||
 22  '      <element name="MGR" type="double" xdb:SQLName="MGR" xdb:SQLType="NUMBER"/> '||
 23  '      <element name="HIREDATE" type="date" xdb:SQLName="HIREDATE" xdb:SQLType="DATE"/> '||
 24  '      <element name="SAL" type="double" xdb:SQLName="SAL" xdb:SQLType="NUMBER"/> '||
 25  '      <element name="COMM" type="double" xdb:SQLName="COMM" xdb:SQLType="NUMBER"/> '||
 26  '     </sequence> '||
 27  '    </complexType> '||
 28  ' </schema> ');
 29  begin
 30            dbms_xmlschema.REGISTERSCHEMA('
http://www.oracle.com/dept.xsd',xsd,true,false,false,false
;
 31  end;
 32  /

A PL/SQL eljárás sikeresen befejez&#337;dött.

SQL> 
SQL> create or replace view dept_xml of xmltype
  2   xmlschema "
http://www.oracle.com/dept.xsd"
element "DEPT_T"
  3   with object ID (extractValue(sys_nc_rowinfo$,'/DEPT_T/DEPTNO'))
  4   as
  5   select dept_t(d.deptno, d.dname, d.loc,
  6                  CAST(MULTISET(
  7                       select emp_t(e.empno, e.ename, e.job, e.mgr, e.hiredate, e.sal, e.comm)
  8                        from scott.emp e
  9                        where e.deptno = d.deptno)
 10                  as emplist_t))
 11    from scott.dept d;

A nézet létrejött.

SQL> 
SQL> select v.sys_nc_rowinfo$.getClobVal()
  2    from dept_xml v
  3    where rownum = 1;

V.SYS_NC_ROWINFO$.GETCLOBVAL()                                                  
--------------------------------------------------------------------------------
<DEPT_T xmlns="
http://www.oracle.com/dept.xsd" >
                                
  <DEPTNO>10</DEPTNO>                                                           
  <DNAME>A                                                                      
                                                                                

SQL> 
SQL> declare
  2          d dept_t;
  3          x xmltype;
  4  begin
  5   select sys_nc_rowinfo$
  6    into x
  7    from dept_xml v
  8    where rownum = 1;
  9  
 10    xmltype.toObject(x,d,'
http://www.oracle.com/dept.xsd','DEPT_T'
;
 11  end;
 12  /
declare
*
Hiba a(z) 1. sorban:
ORA-00600: bels&#337; hiba kód, argumentumai: [qmxiCreColl9], [], [], [], [], [], 
[], [] 
ORA-06512: a(z) "SYS.XMLTYPE", helyen a(z) 0. sornál 
ORA-06512: a(z) helyen a(z) 10. sornál 


SQL> 
SQL> declare
  2          d dept_t;
  3          x xmltype;
  4  begin
  5   select sys_nc_rowinfo$
  6    into x
  7    from dept_xml v
  8    where rownum = 1;
  9  
 10    xmltype.toObject(x,d);
 11  end;
 12  /
declare
*
Hiba a(z) 1. sorban:
ORA-00600: bels&#337; hiba kód, argumentumai: [qmxiCreColl9], [], [], [], [], [], 
[], [] 
ORA-06512: a(z) "SYS.XMLTYPE", helyen a(z) 0. sornál 
ORA-06512: a(z) helyen a(z) 10. sornál 


SQL> exit;
 

Tom Kyte
October 02, 2003 - 9:43 am UTC

there could be more then one cause -- you'll want to contact support (as with all ora-600's) to diagnose.

A reader

A, August 06, 2004 - 5:32 am UTC

Hi tom,
   I was going through most of the document related to xml in your site,but couldn't find one to do following.I will appreciate your help if you could provide some test case with an example.
1)I have been given two file by java team ,the files are
xml schema(.xsd file) and .xml file.
2)They want to load this into the database and extract information.
3)No other info has been provided.
4)Can you tell me is this info sufficient for oracle to extract data.

This is what I did..
SQL> CREATE OR REPLACE DIRECTORY source_dir AS 'c:\test';

Directory created.

SQL> GRANT READ ON DIRECTORY source_dir TO test;

Grant succeeded.

SQL> BEGIN
  2
dbms_xmlschema.registerSchema('account.xsd',xdb_utilities.getXMLfromFile('ac
count.xsd','SOURCE_
DIR'));
  3  end;
  4  /

PL/SQL procedure successfully completed.

--I downloaded this package(getxmlfromfile).

SQL> CREATE TABLE yourtable of XMLType
  2  XMLSCHEMA "account.xsd"
  3  ELEMENT "ACCOUNT";

Table created.

---Here I knew element name..how will I know if the file comes from third party.

SQL> SELECT * FROM yourtable;

no rows selected

SQL> DESC yourtable;
 Name                                      Null?    Type
 ----------------------------------------- --------
----------------------------
TABLE of SYS.XMLTYPE(XMLSchema "account.xsd" Element "ACCOUNT") STORAGE
Object-relational TYPE "XML_

After this I don't know how should I put that xml file
and extract data(it has come from different team,we have no idea what this file contains)
Also i will appreciate if you could tell me if this is valid approach ??
In all your example you used scott.emp,In my case I don't know the structure of anything..I just have this two files to play with.Also I would like to know how xml can be loaded directly in database,I cann't copy and paste as you did in one of your example using scott.emp as I don't know the structure of this xml file.

Cheers 



 

Tom Kyte
August 06, 2004 - 10:13 am UTC

I asked Sean Dillon, our local XML technologist, to take a look at this, here's what he had to say:

--

Hi A fm Aus,

Yes, everything you have done up until now is a sound strategy for storing XML based on a particular XML Schema. There are a number of ways to load your XML into the database, but the way you are doing it is fine. The function you are using to get your XML Schema can be used for the XML files as well (if it's the same kind of function I think it is...)

In the Oracle10g Database Developer's Guide for XML DB, Chapter 3, Example 3-3, you'll find a code sample that inserts XML into an XMLType table, that looks a little like this:

--
INSERT INTO yourtable
VALUES
(
xmltype
(
getFileContent('SOURCE_DIR', 'some_account.xml')
)
);

1 row created.

The following code lists the getFileContent() procedure definition:

CREATE OR REPLACE FUNCTION getFileContent(filename varchar2,
directoryName varchar2 default USER,
charset varchar2 default 'AL32UTF8')
return CLOB
is
fileContent CLOB := NULL;
file bfile := bfilename(directoryName,filename);
dest_offset number := 1;
src_offset number := 1;
lang_context number := 0;
conv_warning number := 0;
begin
DBMS_LOB.createTemporary(fileContent,true,DBMS_LOB.SESSION);
DBMS_LOB.fileopen(file, DBMS_LOB.file_readonly);
DBMS_LOB.loadClobfromFile
(
fileContent,
file,
DBMS_LOB.getLength(file),
dest_offset,
src_offset,
nls_charset_id(charset),
lang_context,
conv_warning
);
DBMS_LOB.fileclose(file);
return fileContent;
end;
/
--

Additionally, you can load your table with SQL*Loader, just check out Chap 27 of the DB Developer's Guide for XML DB, or the Oracle Utilities Guide. If you are using the XML DB Repository, you can load XML data into the repository using FTP or WebDAV. This is a very cool feature, but isn't quite the same as the way you've architected your table. For more info on the XML DB Repository, lots of information to be found in the DB Developer's Guide for XML DB on the Repository as well.

Regarding extracting data, you said you don't know the structure of anything or you have no idea what the file contains... If you are using an XML Schema as the foundation for storing your XML data, you know EXACTLY what those files will contain. XML documents will only conform to an XML Schema if they have the right *format* (I use the term loosely, there are a number of aspects of the XML doc that make it schema-validated...). If you are receiving XML data and it doesn't fit a minimal "type-fit", it will be rejected when you try to insert the document into the table. If you need to store XML data without constraining it to a format in some predefined XML Schema, I suggest using XMLTYPE w/ CLOB storage (instead of object-relational). Don't worry, there's no extra work to do, just do not specify the XML Schema and it'll be an XMLType w/ clob-based storage behind-the-scenes, thereby allowing you to insert any format of (well-defined) XML.

Check out Chapter 6 of the DB Dev Guide : XML DB for data retrieval techniques. Querying XML isn't that complex, but depending on the types of data you want there are a number of ways to do it. You'll find a bunch of them here on AskTom as well, just search for XML and/or XPath.

Hope that helps!


A reader

A, August 06, 2004 - 10:12 pm UTC

Hi Sean,
   Excellent explanation !! Based on that info..

1)The function which you have provided ,will that work on 9ir2(Not able to test today )

2)I saw few examples for retrival technices using xpath.
But how will I know exact xpath,Manually searching path in a big xml file will be very cumbersome.Is there any function which can read the xml and return all xpath.
This is the example I tried..

SQL> select P.PODOCUMENT.extract('/PurchaseOrder/ShippingInstructions/name/text()').getClobVal(),
  2  P.PODOCUMENT.extract('/PurchaseOrder/ShippingInstructions/address/text()').getClobVal()
  3  from PURCHASEORDER P;

P.PODOCUMENT.EXTRACT('/PURCHASEORDER/SHIPPINGINSTRUCTIONS/NAME/TEXT()').GETCLOBV
--------------------------------------------------------------------------------
P.PODOCUMENT.EXTRACT('/PURCHASEORDER/SHIPPINGINSTRUCTIONS/ADDRESS/TEXT()').GETCL
--------------------------------------------------------------------------------
David E. Blake
400 Oracle Parkway Redwood Shores, CA, 94065 USA

Here I knew the xpath,as the file was too small.In a bigger file ,it will be really difficult to go node by node manually and search for the path.Is there any automated fuction which can return the xpath after reading xml files ?? Is there any other way to extract info out of xml ?? 

3)In my previous post(above) while creating a table I knew
the elements name.If the xml file is coming from third party ,how will I know that ?? Is it really needed to have while creating table ??

4)What is the advantages of storing xml on top of xml schema compare to directly loading the xml ??

5)In my previous post,the way I am loading the .xsd file,is that files get stored in database or it still requires the file to be at the  os level at all time ??

I appreciate your help.

Cheers
  
 

Tom Kyte
August 09, 2004 - 3:16 pm UTC

Look at the next follow-up for some of the answers to this question...

For #4, storing XML and associating it to an XML Schema has pros and cons. If done properly, your storage architecture and whether you use an XML Schema or not depends on the behavior of your application and the way you use the data.

Whether you use an XML Schema or not depends on a number of things:
1. Are your XML documents all associated to an XML Schema? If not, clearly you don't use schema-based storage. If so, you still might not...
2. If it is, will ALL the XML data you're putting in the database VALID xml against the XML Schema? Oracle doesn't do full schema-validation when we store the data but we do perform a "type-fit"... this just makes sure simple aspects of the data are correct. For instance, if an element is of datetime, and the data in the element is not a valid datetime, the document will fail to insert. It WONT check things like whether the datetime is in a particular date range or whatnot unless you ask the database to perform an XML Schema validation operation. (this is an option b/c it's an expensive operation and you, the user, may or may not want to perform it). Anyway... these are all options that may effect your choice of storage architecture.

You can either use object-relational storage or CLOB based storage. Object-relational storage is ONLY available of you use xml schema-based xml. You can use CLOB-based storage if you use xml schemas or not. There's a lot of great documentation available that discusses why you'd use one or the other.
Chapter four in the Database Developer's Guide for XML DB has a figure (chart) that outlines why you would store your data one way or the other.

No, the .XSD does not have to be on the operating system. Yes, you can load it into Oracle. You can also refer to XML Schemas available on the network somewhere using a feature called HTTPUri's. Again, look to the doc there's LOT of info available on those too :).

Hope that helps, good luck!

A reader

A, August 08, 2004 - 8:17 am UTC

Cotiuning my previous post ..

1)As they want to retrieve all the data from xml file(s).Is there any way after registering the schema and inserting .xml document,oracle will download all the data from those .xml file to a normal
oracle table where I can simply say "select * from table" and utilise al oracle commands like order by ,where clause etc.

2)If this doesn't happen by default ,is there any way
with which I can do this.

3)I tried Using xpath to retrieve the data,but it's
very combersome as they wanted all the data from xml
file,so I had to look line by line in 4-page xml file
to search all the xpath.Is there any simple way to do
this.

I will appreciate if you can give me some examples.

Cheers


Tom Kyte
August 09, 2004 - 12:14 pm UTC

Hi A, Sean Dillon here...

1. Yes and no. No, Oracle doesn't "download" all the data to a normal Oracle table... When the XML is loaded into XML DB (into Oracle, really), the XML data is stored in one of a few different ways.  This is all explained in the documentation, I'd suggest reading about storage options on OTN for the 9i or 10g Database Developer's Guide - XML DB.  It depends on how you create your XML storage, but yes you can certainly query out the entire XML document.  

ops$sdillon@FUNKDB> create table xmltab ( xmlcol xmltype );
Table created.
 
ops$sdillon@FUNKDB> insert into xmltab values (xmltype('<A><B>some text</B></A>'));
1 row created.
 
ops$sdillon@FUNKDB> select extract(xmlcol, '/') from xmltab;
EXTRACT(XMLCOL,'/')
-----------------------------------------------------------------------------------------------------------------------------------
<A>
  <B>some text</B>
</A>
 
ops$sdillon@FUNKDB> select extract(xmlcol, '/').getclobval() from xmltab;
EXTRACT(XMLCOL,'/').GETCLOBVAL()
--------------------------------------------------------------------------------
<A>
  <B>some text</B>
</A>

(this works the same regardless of whether the xml is associated w/ an xml schema or not)

3.  Yes, obviously you wouldn't want to use XPath for retrieving all the data.  Some people use it for creating a relational view on top of an XML document... a nice way to help non-XML type people using your XML storage without having to learn XPath or DOM or whatnot.

ops$sdillon@FUNKDB> create table xmltab (xmlcol xmltype);
Table created.
 
ops$sdillon@FUNKDB> insert into xmltab values (xmltype('<A><code>1
<val>One</val></A>'));
1 row created.

ops$sdillon@FUNKDB> insert into xmltab values (xmltype('<A>
2
<val>Two</val></A>'));
1 row created.

ops$sdillon@FUNKDB> create view A_VALUES as
2 select extract(xmlcol,'/A/code/text()') code,
3 extract(xmlcol,'/A/val/text()') value
4 from xmltab
5 /
View created.

ops$sdillon@FUNKDB> col CODE for a10
ops$sdillon@FUNKDB> col VALUE for a10
ops$sdillon@FUNKDB> select * from a_values;

CODE VALUE
---------- ----------
1 One
2 Two

Hope that helps!

_smd_
</code>

A reader

A, August 10, 2004 - 8:07 am UTC

Hi sean,
Thanks for your reply,In real time You won't be knowing the name of the field from xml file(It's 4 page) as you have shown in your example..Can you show me following by giving one simple example.I have searched many oracle documentation,but couldn't get ,what I wanted to

1)Load .xsd (xml schema) Using registeschema or any other command

2)load .xml file (Here it's 4 page,lets not do the copy and paste on the screen,real time you don't do that,I don't know the name of the field please remember it has come from third party).I heard oracle does create some tables behind the scene to hold data from xml file,how do I do this,do I have to have special annotation for doing this

3)Dump all the data to a relation table by means of view or whatever .

I am really thankful for your time.

Cheers

Tom Kyte
August 10, 2004 - 2:49 pm UTC

Hi A fm Aus,

Actually, if you use an XML Schema then you would absolutely know the name of the element or attribute you are trying to get data from. I'm not sure which Oracle documentation you're looking at, but let me offer you this. I'm going to point you to some documentation to help you understand Oracle XML DB and how XML can be stored and retrieved. I am also going to point you to some external web sites to help you understand XML Schema a little better.

1. First, go here: </code> http://www.xml.com/pub/a/2000/11/29/schemas/part1.html

This is XML.COM's XML Schema overview.  Read this and understand what XML Schemas are for before you go any further.  

2.  Next, go check out the XML DB Developer's Guide: 
http://docs.oracle.com/docs/cd/B14117_01/appdev.101/b10790/toc.htm

Read chapters 1 and chapter 2.  Once you're done reading those, familiarize yourself w/ the chapters available in the book.  I can continue to paraphrase the documentation for you but it would probably be better for you to find out where the answers are and have you just go find them there.  There are code samples all over the place in that documentation.  There's not a question you've asked that couldn't be answered in that doc.  As for your questions...

Using registerschema is fully explained there, but you could also look in the PL/SQL Packages and Types Reference:  
http://docs.oracle.com/docs/cd/B14117_01/appdev.101/b10802/toc.htm

This document has detailed specs and descriptions of every PL/SQL API included in the db.  The package you are looking for is DBMS_XMLSCHEMA, and can be found in the documentation mentioned above or here's the direct link: 
http://docs.oracle.com/docs/cd/B14117_01/appdev.101/b10802/d_xmlsch.htm#1001337 <code>

As for your questions... #1 is answered in the documentation above. Yes, Oracle creates some tables behind the scenes but this is dependent on you using an XML Schema. Once you have a good grasp on XML Schema concepts and the XML DB Developer's Guide listed above, go to chapters 5 & 6 and read about XML Schema, Storage and Retrieval.

For #3, once you get the above this answer will be blatantly obvious.

Sorry I can't just paste in some quick code, this is a complex technology and there's more to understanding it than a code snippet can provide. If you understand those few chapters I've referenced, you'll be ALL SET. Good luck!

_smd_

A reader

A, August 10, 2004 - 8:16 am UTC

Contiuning from my previous post,to do following in your example ,you will have to know the XPATH and this is where the problem comes.In real time scenario ,you will not be knowing the xpath ,so how will you create the view..

ops$sdillon@FUNKDB> create view A_VALUES as
2 select extract(xmlcol,'/A/code/text()') code,
3 extract(xmlcol,'/A/val/text()') value
4 from xmltab
5 /

cheers

A reader

A, August 13, 2004 - 5:32 am UTC

Hi,
In above example,you created a view.In order to do that you need to know xpath.How will you know xpath in a big xml file.I need to query like normal oracle table.Is it possible without using xpath ?? If yes can you tell me how.Every document I read it uses xpath to do that.Also in above answer you said .. "oracle creates a table behind the scene to store all the data,but it depends on the way xml schema is being used" .Can you clarify this ??

Cheers


Mark, October 27, 2004 - 5:01 pm UTC

Tom,

I am trying to pull in a XSD that is published on our web to validate XML in the database. We are storing the XML as clobs after validation. My problem is when pulling the XSD from the web it is always returned as type text/html. Here is what I am doing.


----------------------------------
SET SERVEROUTPUT ON
declare
httpuri HTTPUriType;
L_CLOB clob;
begin
httpuri := HTTPUriTyp('</code> http://OurMSWebServer/test.xsd' <code>;
L_CLOB := httpuri.getCLOB();

DBMS_OUTPUT.PUT_LINE('--------------------');
DBMS_OUTPUT.PUT_LINE('Type='||httpuri.getContentType());
DBMS_OUTPUT.PUT_LINE('--------------------');
DBMS_OUTPUT.PUT_LINE(SUBSTR(L_CLOB,1,80));
DBMS_OUTPUT.PUT_LINE(SUBSTR(L_CLOB,81,80));
end;
/
--------------------
Type=text/html
--------------------
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html dir=ltr>
<head>
<style>
a:link {font:8pt/11pt verdana;color:FF0000}

The Clob I get is not the XSD but the HTML version of it.
Is there a way to return it as ContentType=text/plain?
Or any other suggestions..

Thanks




Tom Kyte
November 02, 2004 - 12:18 pm UTC

I asked Sean Dillon to take a look at this, and here's what he had to say:
--

This is a function of your web server. On Apache, there is a mime.types file that dictates which file extensions are which content types. So for instance, I ran your test against two documents, a document.xsd and a document.xml. In my mime.types file, xsd was a part of the text/xml and xml was in application/xml:

sdillon@TIGR> declare
2 l_httpuri httpuritype;
3 l_clob clob;
4 begin
5 l_httpuri := httpuritype ('</code> http://sdillon-pc.us.oracle.com/xml/document.xsd'
;
  6    l_clob    := l_httpuri.getclob();
  7  
  8    dbms_output.put_line('-----------------------------');
  9    dbms_output.put_line('type='||l_httpuri.getcontenttype());
 10    dbms_output.put_line('--');
 11    dbms_output.put_line(substr(l_clob,1,80));
 12    dbms_output.put_line(substr(l_clob,81,80));
 13  
 14    -- Now we'll test an XML document
 15  
 16    l_httpuri := httpuritype ('
http://sdillon-pc.us.oracle.com/xml/document.xml'
;
 17    l_clob    := l_httpuri.getclob();
 18  
 19    dbms_output.put_line('-----------------------------');
 20    dbms_output.put_line('type='||l_httpuri.getcontenttype());
 21    dbms_output.put_line('--');
 22    dbms_output.put_line(substr(l_clob,1,80));
 23    dbms_output.put_line(substr(l_clob,81,80));
 24  end;
 25  /
-----------------------------
type=text/xml
--
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="
http://www.o
racle.com/TIGr" 
           xmlns="
http://www.oracle.com/TIGr"
           xml
-----------------------------
type=application/xml
--
<?xml version="1.0" encoding="UTF-8"?>
<!-- 
This script is used to create the r
eports that will go to DHS
-->
<Command xmlns:xsi="
http://www.w3.org/2001/XMLSch

PL/SQL procedure successfully completed.

When I update my mime.types file and add xsd to the line that reads application/xml:

application/xml                 xml xsl xsd

...and re-run this proc I get the following results:

-----------------------------
type=application/xml
--
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="
http://www.o
racle.com/TIGr" 
           xmlns="
http://www.oracle.com/TIGr"
           xml
-----------------------------
type=application/xml
--
<?xml version="1.0" encoding="UTF-8"?>
<!-- 
This script is used to create the r
eports that will go to DHS
-->
<Command xmlns:xsi="
http://www.w3.org/2001/XMLSch <code>

PL/SQL procedure successfully completed.


Either reconfigure IIS (if that's what you're using) or even better, switch over to Apache ;-). Hope that helps!

_smd_
Sean Dillon


select statement returns xmltype()

Nilanjan Ray, February 23, 2005 - 7:27 am UTC

Hi Tom/Sean,

I was trying out your example above. I get different type of output. It would be very useful if you clarify/explain the scenarion..

SQL>insert into xmltab values
  2  (xmltype('<A><code>1
<val>One</val></A>'));

1 row created.

Elapsed: 00:00:00.00
SQL>insert into xmltab values
2 (xmltype('<A>
2
<val>Two</val></A>'));

1 row created.

Elapsed: 00:00:00.00
SQL>commit;

Commit complete.

SQL> select extract(xmlcol,'/A/code/text()') code,
2 extract(xmlcol,'/A/val/text()') value
3 from xmltab;

CODE()
--------------------------------------------------------------------------------
VALUE()
--------------------------------------------------------------------------------
XMLTYPE()
XMLTYPE()

XMLTYPE()
XMLTYPE()

Why is the output XMLTYPE() instead of the data?

Thanks in advance

Regards


</code>
Tom Kyte
March 04, 2005 - 10:12 am UTC

Hi, Sean here.  It's the database version you are using, or the version of SQL*Plus you're using.  In 9iR2, querying an XMLType will display the value.  In your case, you might append "getClobVal() to the end of the extract function, as in:

SQL> col code for a6
SQL> col value for a10
SQL> 
SQL> select extract(xmldoc,'/A/code/text()').getClobVal() code,
  2         extract(xmldoc,'/A/val/text()').getClobVal() value
  3    from xmltest
  4  /

CODE   VALUE
------ ----------
1      One
2      Two 

Is it safe?

Notna, February 18, 2006 - 1:09 pm UTC

Hi,

Would there be any security risks if we open/use this httpuritype to validate our XSD's? How can we enable this feature? Do we have to run extra scripts to use this approach?

Tnx..


Tom Kyte
February 18, 2006 - 4:49 pm UTC

have you checked out the docs? your DBA should know how to install optional features that are not installed (they are the ones that will be doing this for you)

dbms_XMLschema.registerschema not working with a firewall

Robert Corfman, March 03, 2006 - 5:41 pm UTC

I've tried following the examples here to register my schema after I tried following the examples in the 9iR2 documentation (I'm on 9.2.0.6) and I'm stuck right at the beginning.  We haven't done anything with schema validation in the database, I've been using xmlType for a while, but dbms_xmlSchema wasn't even loaded originally, I had to go to the DBA for that. I don't know if something is mis-configured, missing, or there really is a problem. I'm thinkint it might be the firewall...

At least I think it is the firewall causing the problem. It seems to want to validate my schema against www.w3.org, which isn't accessible without specifying a proxy server...

SQL> begin dbms_xmlschema.registerSchema(
  2  '
http://mysite.mycomp.com/architecture/schema/rbom_schema.xsd'
  3  ,utl_http.request('
http://mysite.mycomp.com/architecture/schema/rbom_schema.xsd'
,
  4  TRUE, TRUE, FALSE, FALSE);
  5  end;
  6  /
begin dbms_xmlschema.registerSchema(
*
ERROR at line 1:
ORA-31011: XML parsing failed
ORA-19202: Error occurred in XML processing
LPX-00263: couldn't connect to host www.w3.org port 80
Error at line 1
ORA-06512: at "XDB.DBMS_XMLSCHEMA_INT", line 0
ORA-06512: at "XDB.DBMS_XMLSCHEMA", line 12
ORA-06512: at line 1

I can retrieve the file fine with utl_http.request. The schema validates fine when I use the w3 and M$oft schema validator utilities on the web, but I can't seem to register it. I'm wanting to use a registered schema to validate my aq xml object queue... hurdle one is to get the schema registered ... 

Followup to dbms_XMLschema.registerschema not working with a firewall

Robert Corfman, March 17, 2006 - 2:22 am UTC

Turns out this wasn't the problem it looked like at all. I was trying to use utl_http.request(blah) to retrieve my .xsd file, but the file was about 2 1/2 times larger than the 2000 byte limit for utl_http.request(). The message threw me off on a tangent. When I tweeked the file I started getting other parsing errors which rapidly led me to the correct problem.

The correct way to register a schema located at a url is to use dbms_xmlschema.RegisterURI.
Worked great with the command
begin
dbms_xmlschema.registeruri(
'</code> http://mysite.mycomp.com/architecture/schema/rbom_schema.xsd',
  '
http://mysite.mycomp.com/architecture/schema/rbom_schema.xsd', <code>
true,true,false,false);
end;
/


A reader, March 23, 2006 - 1:23 pm UTC

Tom

Following URL is giving error

</code> http://asktom.oracle.com/~sdillon/asktom/plsqlschema/ <code>


please help

Thanks

Tom Kyte
March 23, 2006 - 1:56 pm UTC

fixed, directory indexing was turned off.

Validating XML timezone

Phil, May 08, 2006 - 2:29 am UTC

Tom,

I am having real problems validating a date with a timezone against a schema, when the schema is loaded into Oracle. My schema uses the xdb:SQLType="TIMESTAMP WITH TIME ZONE" , and creates a field of type TIMESTAMP WITH TZ . This is what I would expect.

However when I validate xml against that schema I can only see to get one format that is an xs:date standard to work and that is 2006-04-18T13:45:45.000000 I was hoping to able to use 2006-04-18T13:45:45+09:00 which is xs:date standard. I am sure that all the dates I am using below are valis xs:date formats.

your thoughts would be much appreciated.

Please find all examples and schemas below.

Oracle rel 9.2.0.6

Regards
Phil


----------------


var schemaURL varchar2(256);
var schemaPath varchar2(256);
begin
:schemaURL := 'dateTimeTest.xsd';
:schemaPath := '/public/dateTimeTest.xsd';
end;
/

PL/SQL procedure successfully completed

call dbms_xmlSchema.deleteSchema(:schemaURL,4);

Call completed.

declare
res boolean;
xmlSchema xmlType := xmlType('<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="</code> http://www.w3.org/2001/XMLSchema"
xmlns:xdb="
http://xmlns.oracle.com/xdb" > <code>
<xs:element name="root" xdb:defaultTable="DATE_TEST_TABLE">
<xs:annotation>
<xs:documentation>Comment describing your root element</xs:documentation>
</xs:annotation>
<xs:complexType xdb:SQLType="DATE_TEST_T">
<xs:sequence>
<xs:element minOccurs="0" name="date" type="xs:date" xdb:SQLType="DATE"/>
<xs:element minOccurs="0" name="dateTime" type="xs:dateTime" xdb:SQLType="TIMESTAMP"/>
<xs:element minOccurs="0" name="dateTimeTZ" type="xs:dateTime" xdb:SQLType="TIMESTAMP WITH TIME ZONE"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
');
begin
begin
dbms_xdb.deleteResource(:schemaPath);
end;
res := dbms_xdb.createResource(:schemaPath,xmlSchema);
end;
/

PL/SQL procedure successfully completed


begin
dbms_xmlschema.registerSchema
(
:schemaURL,
xdbURIType(:schemaPath).getClob(),
true,true,false,true
);
end;
/

PL/SQL procedure successfully completed

desc DATE_TEST_T;

Element Type
---------- ------------------
SYS_XDBPD$ XDB.XDB$RAW_LIST_T
date DATE
dateTime TIMESTAMP
dateTimeTZ TIMESTAMP WITH TZ


declare
xmldoc xmltype :=xmltype('
<root><dateTimeTZ>2006-04-18T13:45:45.000000</dateTimeTZ></root>','dateTimeTest.xsd'
);
begin
xmldoc.schemavalidate();
if xmldoc.isschemavalidated() = 1 then
dbms_output.put_line('Data is valid');
else
dbms_output.put_line('Data is invalid');
end if;
end;
/
Data is valid

PL/SQL procedure successfully completed


declare
xmldoc xmltype :=xmltype('
<root><dateTimeTZ>2006-04-18T13:45:45.0Z</dateTimeTZ></root>','dateTimeTest.xsd'
);
begin
xmldoc.schemavalidate();
if xmldoc.isschemavalidated() = 1 then
dbms_output.put_line('Data is valid');
else
dbms_output.put_line('Data is invalid');
end if;
end;
/

ORA-01830: date format picture ends before converting entire input string
ORA-06512: at "SYS.XMLTYPE", line 0
ORA-06512: at line 6


declare
xmldoc xmltype :=xmltype('
<root><dateTimeTZ>2006-04-18T13:45:45Z</dateTimeTZ></root>','dateTimeTest.xsd'
);
begin
xmldoc.schemavalidate();
if xmldoc.isschemavalidated() = 1 then
dbms_output.put_line('Data is valid');
else
dbms_output.put_line('Data is invalid');
end if;
end;
/
ORA-01858: a non-numeric character was found where a numeric was expected
ORA-06512: at "SYS.XMLTYPE", line 0
ORA-06512: at line 6


declare
xmldoc xmltype :=xmltype('
<root><dateTimeTZ>2006-04-18T13:45:45.0-08:00</dateTimeTZ></root>','dateTimeTest.xsd'
);
begin
xmldoc.schemavalidate();
if xmldoc.isschemavalidated() = 1 then
dbms_output.put_line('Data is valid');
else
dbms_output.put_line('Data is invalid');
end if;
end;
/
ORA-01830: date format picture ends before converting entire input string
ORA-06512: at "SYS.XMLTYPE", line 0
ORA-06512: at line 6

declare
xmldoc xmltype :=xmltype('
<root><dateTimeTZ>2006-04-18T13:45:45-08:00</dateTimeTZ></root>','dateTimeTest.xsd'
);
begin
xmldoc.schemavalidate();
if xmldoc.isschemavalidated() = 1 then
dbms_output.put_line('Data is valid');
else
dbms_output.put_line('Data is invalid');
end if;
end;
/
ORA-01830: date format picture ends before converting entire input string
ORA-06512: at "SYS.XMLTYPE", line 0
ORA-06512: at line 6


More to Explore

CLOB/BLOB/etc

Complete documentation on Securefiles and Large Objects here