Showing posts with label xml. Show all posts
Showing posts with label xml. Show all posts

Monday, 21 September 2015

ora-00904 xml invalid identifier




If you have a XML column as part of a table, for example:

 DESC tab_with_xml_column
 Name                                                  Null?    Type
 ----------------------------------------------------- -------- -------------
 ID                                                             NUMBER
 XML_DATA                                                       XMLTYPE
 CREATED_DATE                                                   DATE


Then when trying to apply XML functionality to that column errors can occur, eg:


SELECT xml_data.EXTRACT('/userdetails/username') FROM tab_with_xml_column
       *
ERROR at line 1:
ORA-00904: "XML_DATA"."EXTRACT": invalid identifier


The solution is to simply enclose the column name within brackets:


SELECT (xml_data).EXTRACT('/userdetails/username') FROM tab_with_xml_column ;

(XML_DATA).EXTRACT('/USERDETAILS/USERNAME')
----------------------------------------------------------------------------------------------------
Fred

Example 2:

SQL > SELECT *
        FROM tab_with_xml_column
       WHERE (xml_data).EXTRACT('/userdetails/username/text()').GETSTRINGVAL()  = 'Fred';

                ID
------------------
XML_DATA
----------------------------------------------------------------------------------------------------
CREATED_D
---------
                 1

   Fred
   pass123

20-SEP-15

This was tested on Oracle 10 and Oracle 11. The table and data used was:

CREATE TABLE tab_with_xml_column
(id               NUMBER ,
 xml_data         XMLTYPE ,
 created_date     DATE
)
/

INSERT INTO tab_with_xml_column
(id ,
 xml_data ,
 created_date)
VALUES 
(1,
 XMLTYPE('
   Fred
   pass123
') ,
SYSDATE) 
/

COMMIT
/



Tuesday, 22 January 2013

Validate XML against an XSD using JDeveloper




Validating xml against an xsd can be achieved thorough JDeveloper, (which is available as a free download).

As an example, if we have the following xsd saved in a file

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">   
   <xs:element name="userdetails">     
      <xs:complexType>       
         <xs:sequence>             
            <xs:element name="username" type="xs:string"/>         
            <xs:element name="password"  type="xs:string"/> 
         </xs:sequence>     
      </xs:complexType>   
   </xs:element> 
</xs:schema>

and the following xml saved in another file

<userdetails>
   <username>Fred</username>
   <password>pass123</password>
</userdetails>

We can open both the files in JDeveloper. Once opened a reference to the XSD needs to be made in the xml file. Modify the xml file and add the following entry to the initial node

    
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  xsi:noNamespaceSchemaLocation="a.xsd">

so the file looks like

<userdetails
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:noNamespaceSchemaLocation="a.xsd">
   <username>Fred</username>
   <password>pass123</password>
</userdetails>

This adds a reference to the xsd file (a.xsd) which resides in the same file location as the xml.

The xml can be validated by right clicking the xml and choosing Validate XML.


If the xml validates against the xsd the following will be displayed in the messages log.


If the xml is modified by adding an element which is not defined in the xsd

 <userdetails>
 <username>Fred</username>
 <password>pass123</password>
 <newelement>dummy value</newelement>
</userdetails>

then when the validation is run an error is displayed


Validating xml with a namespace against an xsd

In the following example the xml is modified to have a default namespace of http://www.onsheld.co.uk/ns1

<?xml version="1.0"?>
<userdetails xmlns="http://www.onsheld.co.uk/ns1">
   <username>Fred</username>
   <password>pass123</password>
</userdetails>

The xsd to validate the xml is show below.  Note the xsd has a reference to the namespace.


<xs:schema elementFormDefault="qualified" 
           targetNamespace="http://www.onsheld.co.uk/ns1" 
           xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="userdetails">
    <xs:complexType>
      <xs:sequence>
        <xs:element type="xs:string" name="username"/>
        <xs:element type="xs:string" name="password"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

The xml would require the following two tags to point the xml to the xsd and indicate validation was required

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
This indicates xml validation

xsi:schemaLocation="http://www.onsheld.co.uk/ns1 http://www.onsheld.co.uk/files/xml_files/a.xsd"

This has two parts, first the namespace followed by a space followed by the name and location of the xsd file (in this case the file is called a.xsd which resides on the web at location http://www.onsheld.co.uk/files/xml_files/a.xsd )

The revised xml would be:

<?xml version="1.0"?>
<userdetails xmlns="http://www.onsheld.co.uk/ns1"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
             xsi:schemaLocation="http://www.onsheld.co.uk/ns1 http://www.onsheld.co.uk/files/xml_files/a.xsd">
   <username>Fred</username>
   <password>pass123</password>
</userdetails>


Further resources


Saturday, 5 January 2013

Validate XML in Oracle against an XSD using DBMS_XMLSCHEMA and XMLTYPE.SCHEMAVALIDATE

The xml below

<userdetails>
   <username>Fred</username>
   <password>pass123</password>
</userdetails>
can be represented by the following XSD

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">   
   <xs:element name="userdetails">     
      <xs:complexType>       
         <xs:sequence>             
            <xs:element name="username" type="xs:string"/>         
            <xs:element name="password"  type="xs:string"/> 
         </xs:sequence>     
      </xs:complexType>   
   </xs:element> 
</xs:schema>
The xsd can be registered with the oracle database by making a call to dbms_xmlschema.registerSchema.
In the example below we have named this xsd as xsd1.xsd

BEGIN    

   dbms_xmlschema.registerSchema(schemaURL   => 'xsd1.xsd', 
                                 schemaDoc   => '<?xml version="1.0" encoding="UTF-8"?> 
                                                 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">   
                                                 <xs:element name="userdetails">     
                                                 <xs:complexType>       
                                                 <xs:sequence>             
                                                 <xs:element name="username" type="xs:string"/>         
                                                 <xs:element name="password"  type="xs:string"/> 
                                                 </xs:sequence>     
                                                 </xs:complexType>   
                                                 </xs:element> 
                                                 </xs:schema>'); 
END; 
/ 
The registered schema can be viewed in the database by accessing the data dictionary all_xml_schemas

SELECT schema 
  FROM all_xml_schemas 
 WHERE schema_url = 'xsd1.xsd'
/

SCHEMA
----------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="WINDOWS-1252"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:oraxdb="http://xmlns.oracle.com/xdb" oraxdb:flags="295" oraxdb:schemaURL="xsd1.xsd" oraxdb:schemaOwner="MYSCHEMA" oraxdb:numProps="3">
   <xs:element name="userdetails" oraxdb:propNumber="2515" oraxdb:global="true" oraxdb:SQLName="userdetails" 
  oraxdb:SQLType="userdetails193_T" oraxdb:SQLSchema="MYSCHEMA" oraxdb:memType="258" oraxdb:defaultTable="userdetails194_TAB" oraxdb:defaultTableSchema="MYSCHEMA">
      <xs:complexType oraxdb:SQLType="userdetails193_T" oraxdb:SQLSchema="MYSCHEMA">
         <xs:sequence>
            <xs:element name="username" type="xs:string" oraxdb:propNumber="2513" oraxdb:global="false"
oraxdb:SQLName="username" oraxdb:SQLType="VARCHAR2" oraxdb:memType="1" oraxdb:SQLInline="true" oraxdb:MemInline="true" oraxdb:JavaInline="true"/>
            <xs:element name="password" type="xs:string" oraxdb:propNumber="2514" oraxdb:global="false"
oraxdb:SQLName="password" oraxdb:SQLType="VARCHAR2" oraxdb:memType="1" oraxdb:SQLInline="true" oraxdb:MemInline="true" oraxdb:JavaInline="true"/>
         </xs:sequence>
      </xs:complexType>
   </xs:element>
</xs:schema>
To validate the xml shown below

<userdetails>
   <username>Fred</username>
   <password>pass123</password>
</userdetails>
we need to add a reference to the xsd we registered earlier and called xsd1.xsd. To the outer node add the reference xsi:noNamespaceSchemaLocation="xsd1.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

<userdetails xsi:noNamespaceSchemaLocation="xsd1.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

We can then make a call to XMLTYPE.schemaValidate to validate the xml against the schema
DECLARE

l_xml         XMLTYPE ;

BEGIN    

   l_xml := XMLTYPE('<userdetails xsi:noNamespaceSchemaLocation="xsd1.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                       <username>Fred</username>
                       <password>pass123</password>
                     </userdetails>');     
                     
   XMLTYPE.schemaValidate(l_xml); 

END; 
/


PL/SQL procedure successfully completed.
The successful execution of the pl/sql indicates the xml was valid. Adding an element that is not defined in the xsd (element newelement) will fail schema validation resulting in an exception being raised

DECLARE

l_xml         XMLTYPE ;

BEGIN    

   l_xml := XMLTYPE('<?xml version="1.0" encoding="UTF-8"?>
                     <userdetails xsi:noNamespaceSchemaLocation="xsd1.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                       <username>Fred</username>
                       <password>pass123</password>
                       <newelement>dummy value</newelement>
                     </userdetails>');     
                     
   XMLTYPE.schemaValidate(l_xml); 

END; 
/

DECLARE
*
ERROR at line 1:
ORA-30937: No schema definition for 'newelement' (namespace '##local') in parent '/userdetails'
ORA-06512: at "SYS.XMLTYPE", line 345
ORA-06512: at line 14
If we don't have an XSD but already have a type representation in the database Oracle allows us to generate an XSD based upon that type

Our original XML

<userdetails>
   <username>Fred</username>
   <password>pass123</password>
</userdetails>
can be represented in the database by the following type

CREATE TYPE user_details_typ AS OBJECT
(
 "username"     VARCHAR2(20) ,
 "password"     VARCHAR2(30)
)
/

Type created.
Note, the attributes username and password have been enclosed in double quotes to preserve their case. To generate the XSD a call to dbms_xmlschema.generateschema is required.

SELECT DBMS_XMLSCHEMA.generateschema('MYSCHEMA', 'USER_DETAILS_TYP', 'userdetails') FROM DUAL ;

This will result in the following XSD being created
<?xml version="1.0"?>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xdb="http://xmlns.oracle.com/xdb" 
xsi:schemaLocation="http://xmlns.oracle.com/xdb http://xmlns.oracle.com/xdb/XDBSchema.xsd">                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
 <xsd:element name="userdetails" type="USER_DETAILS_TYPType" xdb:SQLType="USER_DETAILS_TYP" xdb:SQLSchema="MYSCHEMA"/>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
 <xsd:complexType name="USER_DETAILS_TYPType" xdb:SQLType="USER_DETAILS_TYP" xdb:SQLSchema="MYSCHEMA" xdb:maintainDOM="false">                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
  <xsd:sequence>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
   <xsd:element name="username" xdb:SQLName="username" xdb:SQLType="VARCHAR2">                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
    <xsd:simpleType>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
     <xsd:restriction base="xsd:string">                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
      <xsd:maxLength value="20"/>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
     </xsd:restriction>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
    </xsd:simpleType>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
   </xsd:element>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
   <xsd:element name="password" xdb:SQLName="password" xdb:SQLType="VARCHAR2">                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
    <xsd:simpleType>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
     <xsd:restriction base="xsd:string">                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
      <xsd:maxLength value="30"/>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
     </xsd:restriction>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
    </xsd:simpleType>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
   </xsd:element>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
  </xsd:sequence>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
 </xsd:complexType>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
</xsd:schema> 
 
The parameters passed into dbms_xmlschema.generateschema were:
  • 'MYSCHEMA' - the name of the schema the object (user_details_typ) resides
  • 'USER_DETAILS_TYP' - the name of the object
  • 'userdetails' - the name of the top node
An issue with creating types where the attributes are enclosed in double quotes such as

CREATE TYPE user_details_typ AS OBJECT
(
 "username"     VARCHAR2(20) ,
 "password"     VARCHAR2(30)
)
/

is that in order to reference the type in pl/sql the attributes have to be enclosed in double quotes to preserve their case

DECLARE

l_user_details     user_details_typ ;

BEGIN

   l_user_details := user_details_typ (NULL, NULL) ;
   l_user_details."username" := 'Fred' ;

END ;
/

PL/SQL procedure successfully completed.

Failing to use double quotes will result in an error

DECLARE

l_user_details     user_details_typ ;

BEGIN

   l_user_details := user_details_typ (NULL, NULL) ;
   l_user_details.username := 'Fred' ;

END ;
/

ERROR at line 8:
ORA-06550: line 8, column 19:
PLS-00302: component 'USERNAME' must be declared
ORA-06550: line 8, column 4:
PL/SQL: Statement ignored

Alternatively the object could be created without double quotes and the resulting xml could be tranformed using a style sheet.
The code below transforms xml with uppercase attribute names to xml with lower case attribute names using the xml method transform.

DECLARE

l_xml              XMLTYPE ;
l_xslt             XMLTYPE ;
l_transformed_xml  XMLTYPE ;

BEGIN 

   -- the original xml
   l_xml := XMLTYPE ('<USERDETAILS>
                        <USERNAME>Fred</USERNAME>
                        <PASSWORD>pass123</PASSWORD>
                     </USERDETAILS>') ;
                     
   dbms_output.put_line ('Original xml' || CHR(10)||'---------------------------') ;                  
   dbms_output.put_line (l_xml.getclobval) ;   
   
   
   -- stylesheet to transform all the element names to lower case
   
   l_xslt := XMLTYPE ('<?xml version="1.0" encoding="UTF-8"?>
                        <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
                        <xsl:output method="xml" encoding="UTF-8" version="1.0" />  
                          <xsl:template match="*">
                            <xsl:variable name="vElement"
                              select="translate(name(), ''ABCDEFGHIJKLMNOPQRSTUVWXYZ'',''abcdefghijklmnopqrstuvwxyz'')" />
                            <xsl:element name="{$vElement}">
                              <xsl:apply-templates />
                            </xsl:element>
                          </xsl:template>
                        </xsl:stylesheet>') ;      

   -- apply the xslt to the original xml
   
   l_transformed_xml := l_xml.transform (l_xslt) ;          
   
   dbms_output.put_line ('Transformed xml'|| CHR(10)||'---------------------------') ;      
   dbms_output.put_line (l_transformed_xml.getclobval) ;


END ;
/

Original xml
---------------------------
<USERDETAILS>
                        <USERNAME>Fred</USERNAME>

<PASSWORD>pass123</PASSWORD>
                     </USERDETAILS>
Transformed xml
---------------------------
<userdetails>
<username>Fred</username>
<password>pass123</password>
</userdetails>


PL/SQL procedure successfully completed.


Friday, 14 December 2012

Validate XML against an xsd using Notepad++


The application Notepad++ is free to download. A plugin called xml tools is also free to download. One feature of the plugin is the ability to validate XML against an XSD.

As an example, if we have the following xsd saved in a file

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">   
   <xs:element name="userdetails">     
      <xs:complexType>       
         <xs:sequence>             
            <xs:element name="username" type="xs:string"/>         
            <xs:element name="password"  type="xs:string"/> 
         </xs:sequence>     
      </xs:complexType>   
   </xs:element> 
</xs:schema>
and the following xml saved in another file

<userdetails>
   <username>Fred</username>
   <password>pass123</password>
</userdetails>
we can open the xml file in Notepad++. Once opened the XML can be validated against the XSD by clicking on Plugins --> XML Tools --> Validate now




On clicking Validate now the dialogue box below will be displayed. Navigate to where the xsd is stored on your hard drive and click OK.




If the xml validates against the xsd the following dialogue will be displayed.



If the xml is modified by adding an element which is not defined in the xsd

 <userdetails>
 <username>Fred</username>
 <password>pass123</password>
 <newelement>dummy value</newelement>
</userdetails>
then when the validation is run an error is displayed






Referencing the xsd within the xml file

Instead of navigating to the xsd file the location can be specified in the xml document. In the example below the xsd file is called simple_xsd_1.xsd and is located at http://www.onsheld.co.uk/files/xml_files/simple_xsd_1.xsd
 
<userdetails xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:noNamespaceSchemaLocation="http://www.onsheld.co.uk/files/xml_files/simple_xsd_1.xsd">
   <username>Fred</username>
   <password>pass123</password>
</userdetails>

Validating xml with a namespace against an xsd

The example below shows the same xml but with a default namespace of http://www.onsheld.co.uk/ns1 added

<?xml version="1.0"?>
<userdetails xmlns="http://www.onsheld.co.uk/ns1">
   <username>Fred</username>
   <password>pass123</password>
</userdetails>
The xsd is amended to include the new namespace

<xs:schema elementFormDefault="qualified" 
           targetNamespace="http://www.onsheld.co.uk/ns1" 
           xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="userdetails">
    <xs:complexType>
      <xs:sequence>
        <xs:element type="xs:string" name="username"/>
        <xs:element type="xs:string" name="password"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>
The xml would require the following two tags to point the xml to the xsd and indicate validation was required
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
This indicates xml validation
xsi:schemaLocation="http://www.onsheld.co.uk/ns1 http://www.onsheld.co.uk/files/xml_files/a.xsd"
This has two parts, first the namespace followed by a space followed by the name and location of the xsd file (in this case the file is called a.xsd which resides on the web at location http://www.onsheld.co.uk/files/xml_files/a.xsd )

The revised xml would be:
<?xml version="1.0"?>
<userdetails xmlns="http://www.onsheld.co.uk/ns1"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
             xsi:schemaLocation="http://www.onsheld.co.uk/ns1 http://www.onsheld.co.uk/files/xml_files/a.xsd">
   <username>Fred</username>
   <password>pass123</password>
</userdetails>
If the schema (xsd file) is not accessible then the unable to parse schema file error is returned





Monday, 10 December 2012

Introduction to Oracle XML



XML in Oracle can be stored in the database type XMLTYPE.
To convert string text into an xml document a call to XMLTYPE needs to be made
/* Convert a string into xml */
DECLARE

l_xml      XMLTYPE ;

BEGIN

   l_xml := XMLTYPE ('<Message>Hello World</Message>') ;

END ;
/
XML data can be converted into a clob by the use of the method getclobval

/*Convert a string into xml and then into a clob */
DECLARE

l_xml      XMLTYPE ;
l_clob     CLOB ;

BEGIN

   l_xml := XMLTYPE ('<Message>Hello World</Message>') ;
   
   l_clob := l_xml.getclobval ;

END ;
/
Trying to convert a null xmltype to a clob will result in an error

DECLARE

l_xml      XMLTYPE ;
l_clob     CLOB ;

BEGIN

   l_clob := l_xml.getclobval ;

END ;
/

DECLARE
*
ERROR at line 1:
ORA-30625: method dispatch on NULL SELF argument is disallowed
ORA-06512: at line 10
XML data can be stored in tables.
/* create a table to store xml in */
CREATE TABLE my_xml OF XMLType
/
/* store xml in the table */

DECLARE

l_xml      XMLTYPE ;
l_clob     CLOB ;

BEGIN

   l_xml := XMLTYPE ('<Message>Hello World</Message>') ;
   
   INSERT INTO my_xml VALUES (l_xml) ;
   
   COMMIT ;

END ;
/

PL/SQL procedure successfully completed.

select * from my_xml ;

SYS_NC_ROWINFO$
------------------------------------------------------------------------------
<Message>Hello World</Message>

When selecting large xml documents from a table in SQLPLUS the details may be truncated. To overcome this increase the size of long using the command SET LONG 999999999

Extracting data from xml using xpath

Using the sample xml document

<userdetails>
   <username>Fred</username>
   <password>pass123</password>
</userdetails>
Insert the xml into a database table

DELETE FROM my_xml ;

INSERT INTO my_xml VALUES (XMLTYPE ('<userdetails>
                                       <username>Fred</username>
                                       <password>pass123</password>
                                     </userdetails>')) ;
                                     
COMMIT ;

/* To extract the username */

SELECT extractValue(value(x),
                    '/userdetails/username')
  FROM my_xml x ;

EXTRACTVALUE(VALUE(X),'/USERDETAILS/USERNAME')
----------------------------------------------------------------
Fred
/* To extract the password */

SELECT extractValue(value(x),
                    '/userdetails/password')
  FROM my_xml x ;

EXTRACTVALUE(VALUE(X),'/USERDETAILS/PASSWORD')
-----------------------------------------------------------
pass123
Note, the xpath case must match the case in the xml document. If we pass in password in uppercase then no data will be located

SELECT extractValue(value(x),
                    '/userdetails/PASSWORD')
  FROM my_xml x ;

EXTRACTVALUE(VALUE(X),'/USERDETAILS/PASSWORD')
-------------------------------------------------------

Extracting XML details in pl/sql

DECLARE

l_xml                XMLTYPE ;
l_username           XMLTYPE ;
l_username_varchar   VARCHAR2(20) ;

BEGIN

   l_xml := XMLTYPE ('<userdetails>
                         <username>Fred</username>
                         <password>pass123</password>
                      </userdetails>') ;
       
   -- extract value to clob               
   l_username := l_xml.extract ('/userdetails/password/text()') ;          

   dbms_output.put_line (l_username.getclobval) ;   

   -- extract value to string 
   l_username_varchar := l_xml.extract ('/userdetails/password/text()').getstringval ;

END ;
/

pass123

PL/SQL procedure successfully completed.

The /text() was required to extract the value, without it we would get the node as shown below

DECLARE

l_xml        XMLTYPE ;
l_username   XMLTYPE ;

BEGIN

   l_xml := XMLTYPE ('<userdetails>
                         <username>Fred</username>
                         <password>pass123</password>
                      </userdetails>') ;
                      
   l_username := l_xml.extract ('/userdetails/password') ;          

   dbms_output.put_line (l_username.getclobval) ;   

END ;
/

<password>pass123</password>


PL/SQL procedure successfully completed.
If an XML document has one or more namespaces then these need to be passed into the xpath

DELETE FROM my_xml ;

INSERT INTO my_xml VALUES (XMLTYPE('<userdetails xmlns="http://abc.com/namespaceabc/v1">
                                      <username>Fred</username>
                                      <password>pass123</password>
                                    </userdetails>')) ;

COMMIT ;
The previous xpath will no longer work as this xml has a namespace, (the namespace being http://abc.com/namespaceabc/v1

SELECT extractValue(value(x),
                    '/userdetails/password')
  FROM my_xml x ;
  
EXTRACTVALUE(VALUE(X),'/USERDETAILS/PASSWORD')
-----------------------------------------------------
   
The namespace needs to be passed into the xpath
SELECT extractValue(value(x),
                    '/a:userdetails/a:password' ,
                    'xmlns:a="http://abc.com/namespaceabc/v1"')
  FROM my_xml x ;
  
EXTRACTVALUE(VALUE(X),'/A:USERDETAILS/A:PASSWORD','XMLNS:A="HTTP://ABC.COM/NAMESPACEABC/V1"')
--------------------------------------------------------------------------------------------------
pass123
The use of the letter a for the alias is not relevant. In this example the word fred is used instead of the letter a
SELECT extractValue(value(x),
                    '/fred:userdetails/fred:password' ,
                    'xmlns:fred="http://abc.com/namespaceabc/v1"')
  FROM my_xml x ;

EXTRACTVALUE(VALUE(X),'/FRED:USERDETAILS/FRED:PASSWORD','XMLNS:FRED="HT
-----------------------------------------------------------------------
pass123  
Sometimes values are stored as attributes. In the example below the usertype of ADMIN is held in the attribute called usertype. References can be made to attributes by using the @ symbol.
DECLARE
 
l_xml        XMLTYPE ;
l_usertype   VARCHAR2(10) ;
 
BEGIN
 
   l_xml := XMLTYPE ('<userdetails>
                         <username usertype="ADMIN">Fred</username>
                         <password>pass123</password>
                      </userdetails>') ;
 
   l_usertype := l_xml.extract ('/userdetails/username/@usertype').getstringval ;          
 
   dbms_output.put_line (l_usertype) ;   
 
END ;
/
 
ADMIN
 
PL/SQL procedure successfully completed.