Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Adrian.

Asked: June 12, 2003 - 12:33 pm UTC

Last updated: September 04, 2007 - 1:42 pm UTC

Version: 9.2.0

Viewed 1000+ times

You Asked

The fundamental problem I have is to try and extract data from an XML string stored in a clob, and store this in another table, along with additional fields from the first table.

The table definition and some sample data is at the end of the post.

The data is tick data from a data feed. Within the XML string <F><N>8</N><V>+900</V></F> represents the a new value of +900 for Field Number 8 for the given instrument code etc.

A typical update will only contain the fields that have changed, however based upon that update I need to perform validations on the current status of an instrument.

e.g. I have a rule that says F1 must be less than F2 otherwise raise an alert. If initially I have two fields with values
F1 : 100
F2 : 102
and I recieve an update that contains
<F><N>2</N><V>99</V></F>
then even though I have not recieved information about F1, I still need to perform the check. So I need to select the 'current' value of F1 from the most recent update containing that value.

I thought it might be a good idea to transform the data as it arrives into a different format, similar to:

Instrument_code varchar2(90)
Tick_Type number
ID number
FID number
FIDValue varchar2(30)

Once I have this, then I can create a view for the 'current' state of any instrument_code, and can relativly easily see how all the updates progressed throughout the day.

My problem is getting the data into the new layout. One option would be to write a parser to extract the sections I want, and insert the data.

Another perhaps better option would be to use some of the new XML features supplied. I tried playing around with DBMS_XMLSAVE, and managed to process the <F><N><V></V></N></F> into a table, but I couldn't see a way of adding the other columns of data to this table.

This is what I tried. Where ACH_NV is a table with columns N, and V, and occasionly various other columns as i tried different things. ACH_TEST is a subset of the SWX_Updates table (30 rows instead of 3 million)

declare
l_ctx dbms_xmlsave.ctxtype;
l_rows pls_integer;
l_clob clob;
begin
for rec in (select tick_data
from ach_test) loop
l_ctx := dbms_xmlsave.newcontext('ACH_NV');
dbms_xmlsave.setrowtag(l_ctx, 'F');
l_clob := rec.tick_data;
l_rows := DBMS_XMLSave.insertXML(l_ctx, l_clob);
dbms_xmlsave.closeContext(l_ctx);
end loop;
end;
/


Are there any tricks I am missing with PL/SQL? I am new to the XMLDB features, and have so far spent a few days trying out different scenarios. However I am mainly a DBA, and Java/XML are not really my areas of expertise. Would any solution only apply to 9i? Currently the database is 8.1.7, but I have plans to migrate it to 9i in the future.

Thanks in advance for your help

Adrian


desc swx_updates;
Name Null? Type
----------------------------- -------- --------------------
INSTRUMENT_CODE NOT NULL VARCHAR2(90)
SNAP_TIME NUMBER
TICK_DATA CLOB
TICK_TYPE NUMBER
ID NUMBER
TARGET_PARTITION NUMBER
CAPTURE_DATE DATE
BID NUMBER
ASK NUMBER
Some sample data:

17:02:41 neiqt@ACH9I.US.ORACLE.COM> set long 99999
17:02:44 neiqt@ACH9I.US.ORACLE.COM> select * from swx_updates where instrument_code = 'ZZZZ.S' and rownum <= 10;

INSTRUMENT_CODE SNAP_TIME
------------------------------------------------------------------------------------------ ----------
TICK_DATA TICK_TYPE ID TARGET_PARTITION
-------------------------------------------------------------------------------- ---------- ---------- ----------------
CAPTURE_DATE BID ASK
-------------------- ---------- ----------
ZZZZ.S 1.0529E+12
<?xml version="1.0"?><Record><Type>VERIFY</Type><Source>SSL4.5</Source><Instrume 318 311777598
nt>ZZZZ.S</Instrument><F><N>1</N><V>4022</V></F><F><N>2</N><V>116</V></F><F><N>3
</N><V>CONZZETA HLDNG I</V></F><F><N>4</N><V>0</V></F><F><N>6</N><V>+910</V></F>
<F><N>7</N><V>+910</V></F><F><N>8</N><V>+900</V></F><F><N>9</N><V>+900</V></F><F
><N>10</N><V>+900</V></F><F><N>11</N><V>-15</V></F><F><N>12</N><V>+921</V></F><F
><N>13</N><V>+900</V></F><F><N>14</N><V>1</V></F><F><N>15</N><V>756</V></F><F><N
>16</N><V>14 MAY 2003</V></F><F><N>18</N><V>12:38</V></F><F><N>19</N><V>+921</V>
</F><F><N>21</N><V>+925</V></F><F><N>22</N><V>+890</V></F><F><N>25</N><V>+910</V
></F><F><N>28</N><V> </V></F><F><N>29</N><V> : </V></F><F><N>30</N><V>+20</
V></F><F><N>31</N><V>+20</V></F><F><N>32</N><V>+155</V></F><F><N>34</N><V>+94.10
</V></F><F><N>35</N><V>+2.703</V></F><F><N>36</N><V>+9.83</V></F><F><N>38</N><V>
09 MAY 2003</V></F><F><N>53</N><V>0</V></F><F><N>56</N><V>-1.62</V></F><F><N>71<
/N><V>+25.00</V></F><F><N>75</N><V>+0</V></F><F><N>76</N><V>+0</V></F><F><N>77</
N><V>+9</V></F><F><N>78</N><V>000000265798</V></F><F><N>79</N><V>13 MAY 2003</V>
</F><F><N>90</N><V>+1129</V></F><F><N>91</N><V>+850</V></F><F><N>105</N><V>****<
/V></F><F><N>100</N><V>+140925</V></F><F><N>110</N><V>0</V></F><F><N>111</N><V>0
</V></F><F><N>117</N><V>0</V></F><F><N>118</N><V>0</V></F><F><N>289</N><V>+0</V>
</F><F><N>259</N><V>113</V></F><F><N>5</N><V>14:39</V></F><F><N>37</N><V>10</V><
/F><F><N>39</N><V>09 MAY 2003</V></F><F><N>55</N><V>+0</V></F><F><N>66</N><V>+0<
/V></F><F><N>67</N><V> </V></F><F><N>68</N><V> </V></F><F><N
>98</N><V>+940</V></F><F><N>104</N><V>0</V></F><F><N>131</N><V>215</V></F><F><N>
134</N><V>+0</V></F><F><N>162</N><V></V></F><F><N>163</N><V></V></F><F><N>178</N
><V>+10</V></F><F><N>291</N><V>+0</V></F><F><N>292</N><V>+0</V></F><F><N>345</N>
<V> </V></F><F><N>346</N><V> </V></F><F><N>350</N><V>13 MAY 2002</V></F><F><N>35
1</N><V>09 APR 2003</V></F><F><N>372</N><V>+0.00</V></F><F><N>373</N><V>+0</V></
F><F><N>374</N><V>1</V></F><F><N>375</N><V> : : </V></F><F><N>379</N><V>14:38
:07</V></F><F><N>380</N><V>1</V></F><F><N>436</N><V>+0</V></F><F><N>437</N><V>+0
</V></F><F><N>438</N><V>+0</V></F><F><N>439</N><V>+0</V></F><F><N>440</N><V>+0</
V></F><F><N>441</N><V>+0</V></F><F><N>442</N><V>+0</V></F><F><N>443</N><V>+0</V>
</F><F><N>444</N><V>+0</V></F><F><N>445</N><V>+0</V></F><F><N>728</N><V>ZZZZ.S
</V></F><F><N>730</N><V>+0</V></F><F><N>731</N><V>+0</V></F><F><N>732</N><V>+0
</V></F><F><N>733</N><V>+0</V></F><F><N>734</N><V>+0</V></F><F><N>735</N><V>+0</
V></F><F><N>736</N><V>+0</V></F><F><N>737</N><V>+0</V></F><F><N>738</N><V>+0</V>
</F><F><N>739</N><V>+0</V></F><F><N>740</N><V>+0</V></F><F><N>741</N><V>+0</V></
F><F><N>742</N><V>+0</V></F><F><N>743</N><V>+0</V></F><F><N>744</N><V>+0</V></F>
<F><N>745</N><V>+0</V></F><F><N>746</N><V>+0</V></F><F><N>747</N><V>+0</V></F><F
><N>800</N><V>0#.SMIGS</V></F><F><N>801</N><V></V></F><F><N>825</N><V>0</V></F><
F><N>869</N><V>28</V></F><F><N>899</N><V>+0</V></F><F><N>947</N><V>+0</V></F><F>
<N>963</N><V>+925</V></F><F><N>967</N><V>ZZZZ.SB2</V></F><F><N>975</N><V></V></F
><F><N>976</N><V></V></F><F><N>977</N><V></V></F><F><N>978</N><V></V></F><F><N>9
79</N><V></V></F><F><N>996</N><V>+155</V></F><F><N>997</N><V>+0</V></F><F><N>998
</N><V>+940.00</V></F><F><N>999</N><V>+0</V></F><F><N>1000</N><V>OnVol </V></F><
F><N>1001</N><V>OffVol</V></F><F><N>1002</N><V>TX03 </V></F><F><N>1003</N><V></
V></F><F><N>1021</N><V>+0</V></F><F><N>1023</N><V>+0</V></F><F><N>1028</N><V>13
MAY 2003</V></F><F><N>1030</N><V>+0</V></F><F><N>1031</N><V>+900</V></F><F><N>10
35</N><V>CZH </V></F><F><N>1036</N><V></V></F><F><N>1037</N><V></V></F><F><N>1
051</N><V> </V></F><F><N>1055</N><V>25</V></F><F><N>1056</N><V>CH00026
57986</V></F><F><N>1067</N><V> : : </V></F><F><N>1080</N><V>la@</V></F><F><N>
1352</N><V></V></F><F><N>1379</N><V>+909.19</V></F><F><N>1383</N><V>@HB</V></F><
F><N>1465</N><V>+0</V></F><F><N>1496</N><V>+0.00</V></F><F><N>1501</N><V></V></F
><F><N>1709</N><V>335</V></F><F><N>1787</N><V>+0</V></F><F><N>1788</N><V>
</V></F><F><N>2127</N><V>-1.60</V></F><F><N>2128</N><V>-18.19</V></F><F><N>2
320</N><V></V></F><F><N>2382</N><V>0</V></F><F><N>2388</N><V>+909.194</V></F><F>
<N>2405</N><V>+0.00</V></F><F><N>2406</N><V>+0.00</V></F><F><N>2407</N><V>+0</V>
</F><F><N>2408</N><V>+0</V></F><F><N>2409</N><V>+0</V></F><F><N>2410</N><V>+0</V
></F><F><N>2411</N><V>+0</V></F><F><N>2412</N><V>+0</V></F><F><N>2413</N><V>+0</
V></F><F><N>2414</N><V>+0</V></F><F><N>2415</N><V>+0</V></F><F><N>2416</N><V>+0<
/V></F><F><N>2417</N><V>+0</V></F><F><N>2418</N><V>+0</V></F><F><N>2419</N><V>+0
</V></F><F><N>2420</N><V>+0</V></F><F><N>2421</N><V>+0</V></F><F><N>2422</N><V>+
0</V></F><F><N>2423</N><V>+0</V></F><F><N>2424</N><V>+0</V></F><F><N>2425</N><V>
+0</V></F><F><N>2426</N><V>+0</V></F><F><N>2427</N><V>+0</V></F><F><N>2428</N><V
>+0</V></F><F><N>2429</N><V>+0</V></F><F><N>2430</N><V>+0</V></F><F><N>2431</N><
V>+0</V></F><F><N>2432</N><V>+0</V></F><F><N>2433</N><V>+0</V></F><F><N>2434</N>
<V>+0</V></F><F><N>2435</N><V>+0</V></F><F><N>2436</N><V>+0</V></F><F><N>3131</N
><V>+0</V></F><F><N>3132</N><V>+0</V></F></Record>
14-MAY-2003 15:56:03 890 910

ZZZZ.S 1.0529E+12
<?xml version="1.0"?><Record><Type>UPDATE</Type><Source>SSL4.5</Source><Instrume 316 311793940
nt>ZZZZ.S</Instrument><F><N>118</N><V>214</V></F><F><N>379</N><V>17:20:00</V></F
><F><N>963</N><V>+910</V></F><F><N>1028</N><V>14 MAY 2003</V></F><F><N>1030</N><
V>+0</V></F></Record>
14-MAY-2003 16:13:23

ZZZZ.S 1.0529E+12
<?xml version="1.0"?><Record><Type>UPDATE</Type><Source>SSL4.5</Source><Instrume 316 311793943
nt>ZZZZ.S</Instrument><F><N>131</N><V>214</V></F><F><N>379</N><V>17:20:00</V></F
><F><N>1031</N><V>+0</V></F></Record>
14-MAY-2003 16:13:23

ZZZZ.S 1.0529E+12
<?xml version="1.0"?><Record><Type>UPDATE</Type><Source>SSL4.5</Source><Instrume 316 311804017
nt>ZZZZ.S</Instrument><F><N>379</N><V>17:20:00</V></F></Record>
14-MAY-2003 16:25:28

ZZZZ.S 1.0529E+12
<?xml version="1.0"?><Record><Type>UPDATE</Type><Source>SSL4.5</Source><Instrume 316 311804018
nt>ZZZZ.S</Instrument><F><N>118</N><V>208</V></F><F><N>379</N><V>17:31:54</V></F
></Record>
14-MAY-2003 16:25:28

ZZZZ.S 1.0529E+12
<?xml version="1.0"?><Record><Type>UPDATE</Type><Source>SSL4.5</Source><Instrume 316 311804019
nt>ZZZZ.S</Instrument><F><N>379</N><V>17:31:54</V></F></Record>
14-MAY-2003 16:25:28

ZZZZ.S 1.0529E+12
<?xml version="1.0"?><Record><Type>UPDATE</Type><Source>SSL4.5</Source><Instrume 316 311968914
nt>ZZZZ.S</Instrument><F><N>5</N><V>20:35</V></F><F><N>32</N><V>+155</V></F><F><
N>100</N><V>+140925</V></F><F><N>118</N><V>166</V></F><F><N>178</N><V>+10</V></F
><F><N>372</N><V>+140925.00</V></F><F><N>373</N><V>+155</V></F><F><N>374</N><V>4
</V></F><F><N>379</N><V>14:25:07</V></F></Record>
14-MAY-2003 21:28:24

ZZZZ.S 1.0529E+12
<?xml version="1.0"?><Record><Type>UPDATE</Type><Source>SSL4.5</Source><Instrume 316 311971877
nt>ZZZZ.S</Instrument><F><N>131</N><V>0</V></F></Record>
14-MAY-2003 21:38:32

ZZZZ.S 1.0530E+12
<?xml version="1.0"?><Record><Type>UNKNOWN</Type><Source>SSL4.5</Source><Instrum 312 312003489
ent>ZZZZ.S</Instrument><F><N>6</N><V>+0</V></F><F><N>7</N><V>+0</V></F><F><N>8</
N><V>+0</V></F><F><N>9</N><V>+0</V></F><F><N>10</N><V>+0</V></F><F><N>11</N><V>+
0</V></F><F><N>12</N><V>+0</V></F><F><N>13</N><V>+0</V></F><F><N>22</N><V>+0</V>
</F><F><N>25</N><V>+0</V></F><F><N>19</N><V>+0</V></F><F><N>56</N><V>+0.00</V></
F><F><N>32</N><V>+0</V></F><F><N>30</N><V>+0</V></F><F><N>31</N><V>+0</V></F><F>
<N>14</N><V>0</V></F><F><N>118</N><V>0</V></F><F><N>110</N><V>0</V></F><F><N>111
</N><V>0</V></F><F><N>21</N><V>+910</V></F><F><N>35</N><V>+2.747</V></F><F><N>36
</N><V>+9.67</V></F><F><N>77</N><V>+0</V></F><F><N>79</N><V>14 MAY 2003</V></F><
F><N>100</N><V>+0</V></F><F><N>131</N><V>0</V></F><F><N>178</N><V>+0</V></F><F><
N>345</N><V> </V></F><F><N>346</N><V> </V></F><F><N>372</N><V>+0.00</V></F><F><N
>373</N><V>+0</V></F><F><N>374</N><V>0</V></F><F><N>996</N><V>+0</V></F><F><N>99
7</N><V>+0</V></F><F><N>999</N><V>+0</V></F><F><N>1031</N><V>+0</V></F><F><N>137
9</N><V>+0.00</V></F><F><N>2127</N><V>-3.19</V></F><F><N>2388</N><V>+0</V></F></
Record>
15-MAY-2003 04:45:37

ZZZZ.S 1.0530E+12
<?xml version="1.0"?><Record><Type>UPDATE</Type><Source>SSL4.5</Source><Instrume 316 312006539
nt>ZZZZ.S</Instrument><F><N>118</N><V>208</V></F><F><N>379</N><V>06:00:00</V></F
></Record>
15-MAY-2003 05:39:10


10 rows selected.

Elapsed: 00:00:04.07
17:03:05 neiqt@ACH9I.US.ORACLE.COM> spool off



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:
--------------

Hiya Adrian,

You want to look into the XMLType in 9i R2. There are some cool features you can use to accomplish what you want to do. XMLSEQUENCE is a cool feature that will break down many nodes into individual xmltypes, and then the TABLE function will turn those into rows. This will make sense in the code sample below. Basically, I'd use a table to insert the XML document into, and then have an on insert trigger manage breaking out the values:

--Sample table for xml documents. The additional VARCHAR2 columns are for
--example purposes only, you may or may not choose to extract these values
--in the trigger.

sdillon@SLAP92> create table xmldocs (
2 xmldoc xmltype,
3 thetype varchar2(50),
4 source varchar2(50),
5 instrument varchar2(50) )
6 /
Table created.

--Sample table to hold the F Node values:

sdillon@SLAP92> create table fvals (
2 n varchar2(10),
3 v varchar2(10)
4 )
5 /
Table created.

--An on-insert trigger to extract the values into the additional VARCHAR2
--columns and into the FVALS table:

sdillon@SLAP92> create or replace trigger xmldocs_bifert
2 before insert on xmldocs
3 for each row
4 begin
5 if (:new.xmldoc is null) then
6 return;
7 end if;
8
9 select xmltype.getstringval(:new.xmldoc.extract('/Record/Type/text()')),
10 xmltype.getstringval(:new.xmldoc.extract('/Record/Source/text()'))
11 xmltype.getstringval(:new.xmldoc.extract('/Record/Instrument/text(
12 into :new.thetype, :new.source, :new.instrument
13 from dual;
14
15 for i in ( select xmltype.extract(value(t), '/F/N/text()' ).getstringval(
16 xmltype.extract(value(t), '/F/V/text()' ).getstringval(
17 from table( xmlsequence( :new.xmldoc.extract('/Record/F') )
18 loop
19 insert into fvals values (i.N, i.V);
20 end loop;
21 end xmldocs_bifert;
22 /
Trigger created.

--With the trigger, all you need to do is insert the document at this point:

sdillon@SLAP92> insert into xmldocs (xmldoc)
2 values (xmltype.createxml(
3 '<?xml version="1.0"?>
4 <Record>
5 <Type>VERIFY</Type>
6 <Source>SSL4.5</Source>
7 <Instrument>ZZZZ.S</Instrument>
8 <F>
9 <N>1</N>
10 <V>4022</V>
11 </F>
12 <F>
13 <N>2</N>
14 <V>116</V>
15 </F>
16 </Record>'))
17 /
1 row created.

--And automatically, the values are extracted appropriately and inserted
--into the tables by the trigger:

sdillon@SLAP92> select thetype, source, instrument
2 from xmldocs
3 /

THETYPE SOURCE INSTRUMENT
---------- ---------- ----------
VERIFY SSL4.5 ZZZZ.S

sdillon@SLAP92> select *
2 from fvals
3 /

N V
---------- ----------
1 4022
2 116

I hope that helps!

_smd_



Rating

  (10 ratings)

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

Comments

Useful but trigger trimmed from the right side

Sasa, August 18, 2003 - 4:23 am UTC

Hi Tom,

Actually this question is intended for Sean Dillon (XML guru)
for this very usefull script but trigger is trimmed from the right side so it should look like this.

CREATE OR REPLACE TRIGGER xmldocs_bifert
before insert on xmldocs
for each row
begin
if (:new.xmldoc is null) then
return;
end if;
--
select xmltype.getstringval(:new.xmldoc.extract('/Record/Type/text()')),
xmltype.getstringval(:new.xmldoc.extract('/Record/Source/text()')),
xmltype.getstringval(:new.xmldoc.extract('/Record/Instrument/text()'))
into :new.thetype, :new.source, :new.instrument
from dual;
--
for i in ( select xmltype.extract(value(t), '/F/N/text()' ).getstringval() as N,
xmltype.extract(value(t), '/F/V/text()' ).getstringval() as V
from table( xmlsequence( :new.xmldoc.extract('/Record/F'))) t
)
loop
insert into fvals values (i.N, i.V);
end loop;
end xmldocs_bifert;
/

Anyway, thanks.

Tom Kyte
August 18, 2003 - 9:07 am UTC

Hi, Sean here. Right you are, it looks like the trigger was trimmed on the right... (doh!) Thanks for pointing it out!

Thanks

Adrian Carlson-Hedges, August 18, 2003 - 9:37 am UTC

Very helpful. Thank you.

Need some more input

student, March 09, 2004 - 11:10 pm UTC

First I would like to thank for such a nice site, learnt a lot from this GREAT site. Not sure if this is the correct thread, I am not getting a chance to ask in a new question.

Need your help on the following.

I will have to generate a RDF report based on the XML information stored in a CLOB column.
Following is the structure of the XML CLOB.
Could you please suggest how can I load the XML in a table,so that,
we could easily query the table rows to print the RDF report.
How do I load the XML in a table ? what are the possible table columns I will have to keep ?

I am very new to XML tech. Please help.

<SHOW_SHIPMENT_005>
<CNTROLAREA>
<BSR>
<VERB value="SHOW">SHOWN</VERB>
<NOUN value="SHIPMENT">SHIPMENT</NOUN>
<REVISION value="005">005</REVISION>
</BSR>
<SENDER>
<LOGICALID>GLEN-STAMFORD</LOGICALID>
<COMPONENT>ASN</COMPONENT>
<TASK>SHOW</TASK>
<REFERENCEID>2002-62949-1673*110664-1</REFERENCEID>
<CONFIRMATION/>

<LANGUAGE>ENG</LANGUAGE>
<CODEPAGE/>
<AUTHID>STAMFORD</AUTHID>
</SENDER>
<DATETIME qualifier="CREATION">
<YEAR>2004</YEAR>
<MONTH>02</MONTH>
<DAY>12</DAY>
<HOUR>10</HOUR>
<MINUTE>51</MINUTE>
<SECOND>01</SECOND>
<SUBSECOND>0000</SUBSECOND>
<TIMEZONE>+0000</TIMEZONE>

</DATETIME>
</CNTROLAREA>
<DATAAREA>
<SHOW_SHIPMENT>
<SHIPMENT>
<DATETIME qualifier="DOCUMENT">
<YEAR>2004</YEAR>
<MONTH>02</MONTH>
<DAY>12</DAY>
<HOUR>10</HOUR>
<MINUTE>51</MINUTE>
<SECOND>01</SECOND>
<SUBSECOND>0000</SUBSECOND>

<TIMEZONE>+0000</TIMEZONE>
</DATETIME>
<DATETIME qualifier="SHIP">
<YEAR>2004</YEAR>
<MONTH>01</MONTH>
<DAY>05</DAY>
<HOUR>12</HOUR>
<MINUTE>00</MINUTE>
<SECOND>00</SECOND>
<SUBSECOND>0000</SUBSECOND>
<TIMEZONE>+0000</TIMEZONE>
</DATETIME>
<DATETIME qualifier="DELIVSCHED">

<YEAR>2004</YEAR>
<MONTH>01</MONTH>
<DAY>05</DAY>
<HOUR>12</HOUR>
<MINUTE>00</MINUTE>
<SECOND>00</SECOND>
<SUBSECOND>0000</SUBSECOND>
<TIMEZONE>+0000</TIMEZONE>
</DATETIME>
<QUANTITY qualifier="NETWEIGHT">
<VALUE>45415</VALUE>
<NUMOFDEC/>
<SIGN/>

<UOM>LB</UOM>
</QUANTITY>
<QUANTITY qualifier="TOTWEIGHT">
<VALUE>45415</VALUE>
<NUMOFDEC/>
<SIGN/>
<UOM>LB</UOM>
</QUANTITY>
<DOCUMENTID>2002-62949-1673*110664-1</DOCUMENTID>
<SHIPPERID/>
<NOTES index="1">HOLLY</NOTES>
<USERAREA>
<CARRIERCODE/>

<QUANTITY qualifier="OTHER">
<VALUE>45415</VALUE>
<NUMOFDEC>4</NUMOFDEC>
<SIGN/>
<UOM>LB</UOM>
</QUANTITY>
<ATTRIBUTE9>105165*110664-1</ATTRIBUTE9>
</USERAREA>
<PARTNER>
<PARTNRID/>
<PARTNRTYPE>ShipFrom</PARTNRTYPE>
<NAME index="1">core LTD</NAME>
<PARTNRIDX>STAMFORD</PARTNRIDX>

<ADDRESS>
<CITY/>
<COUNTRY/>
<POSTALCODE/>
<STATEPROVN/>
</ADDRESS>
</PARTNER>
<PARTNER>
<PARTNRID/>
<PARTNRTYPE>ShipTo</PARTNRTYPE>
<NAME index="1"/>
<PARTNRIDX>CITY_10538</PARTNRIDX>
<ADDRESS>

<ADDRLINE index="1"/>
<ADDRLINE index="2"/>
<CITY/>
<COUNTRY/>
<POSTALCODE/>
<STATEPROVN/>
</ADDRESS>
</PARTNER>
<SHIPITEM>
<QUANTITY qualifier="ITEM">
<VALUE>45415</VALUE>
<NUMOFDEC/>
<SIGN>+ </SIGN>

<UOM>LB</UOM>
</QUANTITY>
<ITEM/>
<ITEMX/>
<NOTES index="1">MT HOLLY SC</NOTES>
<DOCUMNTREF>
<DOCTYPE>PurchaseOrder</DOCTYPE>
<DOCUMENTID>110008888</DOCUMENTID>
<PARTNRID/>
<PARTNRTYPE/>
<DESCRIPTN/>
<DOCUMENTRV/>
<LINENUM>2</LINENUM>

<SCHLINENUM>1</SCHLINENUM>
<USERAREA>
<DOCUMENTRELEASE/>
</USERAREA>
</DOCUMNTREF>
<DOCUMNTREF>
<DOCTYPE>PackingSlip</DOCTYPE>
<DOCUMENTID>COEE^1318</DOCUMENTID>
<PARTNRID/>
<PARTNRTYPE/>
<DESCRIPTN/>
<DOCUMENTRV/>
<LINENUM/>

<SCHLINENUM/>
<USERAREA/>
</DOCUMNTREF>
</SHIPITEM>
<DOCUMNTREF>
<DOCTYPE>BillOfLading</DOCTYPE>
<DOCUMENTID>105555</DOCUMENTID>
<PARTNRID/>
<PARTNRTYPE/>
<DESCRIPTN/>
<DOCUMENTRV/>
<LINENUM/>
<SCHLINENUM/>

<USERAREA/>
</DOCUMNTREF>
<DOCUMNTREF>
<DOCTYPE>PackingSlip</DOCTYPE>
<DOCUMENTID>COEE^1318</DOCUMENTID>
<PARTNRID/>
<PARTNRTYPE/>
<DESCRIPTN/>
<DOCUMENTRV/>
<LINENUM/>
<SCHLINENUM/>
<USERAREA/>
</DOCUMNTREF>

</SHIPMENT>
</SHOW_SHIPMENT>
</DATAAREA>
</SHOW_SHIPMENT_005>


Tom Kyte
March 10, 2004 - 8:57 am UTC

</code> https://docs.oracle.com#index-XML <code>

given that I don't really know what an "rdf" is, I'll point you to the XML developers guide (you'll want to at least skim it -- not too long - so as to be aware of your options. then come back and read it in depth)

one solution would be to give oracle the dtd/xmlschema -- give it the opportunity to create the object types, load the xml into that and just start querying it.

there are many other options as well.

A reader, March 10, 2004 - 9:44 am UTC

Hi Tom,

He is referring to Oracle Reports.
When reports are saved it has the extension of .rdf.


Tom Kyte
March 10, 2004 - 3:33 pm UTC

right -- then I don't see how you would convert xml into rdf but you can

a) load the xml into the database so that
b) you can run reports against data in the database

Notes for hierarchy data

A reader, July 07, 2005 - 1:42 pm UTC

Hi Tom,

This is a data model design question...

Say I have a star schema and we have report pages on different levels of group by on the data. Now we want to let the user to add notes to any level, or even the most details level - the fact record itself.

E.g. when the user is viewing a summary report group by regions, he can add a note for that page. If he is viewing one single order line detail, he can add a note to that order line as well.


I am thinking using XML maybe good idea for this, storing the "group by" path...

Do you think this a good idea? (Give that the notes will be sparse compared to the # of rows in fact).

Tom Kyte
July 07, 2005 - 2:29 pm UTC

seems this is an attribute of a report meta data object (eg: an entity you might not yet have - or maybe you do)

Sounds like a clob in a detail table related to a report table with a list of "reports"

What if you're trying to load diverse CDATA?

James Pollard, July 25, 2005 - 11:28 am UTC

Tom,

I tried to manipulate the code above to utilize...but the insert statement doesn't seem to like all of the special characters in my XML file below. I'm sending the XML packet to Oracle via ColdFusion.

Here's the error I get once the stored procedure is called.

[Macromedia][Oracle JDBC Driver][Oracle]ORA-01461: can bind a LONG value only for insert into a LONG column ORA-06512: at "SASSOH.LOADXML", line 3 ORA-06512: at line 1

Thanks in advance for you help.

Jim

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


CREATE TABLE JOBS
(
ID NUMBER,
HOST VARCHAR2(100 BYTE),
SEARCH VARCHAR2(100 BYTE),
LINK VARCHAR2(4000 BYTE),
POSTDATE DATE,
TITLE VARCHAR2(4000 BYTE),
COMPANY VARCHAR2(4000 BYTE),
LOCATION VARCHAR2(100 BYTE),
D_UPD DATE,
STATE VARCHAR2(100 BYTE),
CITY VARCHAR2(100 BYTE),
TITLE_NOLINK VARCHAR2(100 BYTE),
COMPANY_NOLINK VARCHAR2(100 BYTE),
XMLDOC SYS.XMLTYPE
)

CREATE OR REPLACE PROCEDURE LoadXML (cfxml in varchar) AS
begin
insert into JOBS (xmldoc) values (xmltype.createxml(cfxml));
end;
/

CREATE OR REPLACE TRIGGER jobs_bifert
before insert on jobs
for each row
begin
if (:new.xmldoc is null) then
return;
end if;
select xmltype.getstringval(:new.xmldoc.extract('/row/date/text()')),
xmltype.getstringval(:new.xmldoc.extract('/row/title/text()')),
xmltype.getstringval(:new.xmldoc.extract('/row/company/text()')),
xmltype.getstringval(:new.xmldoc.extract('/row/location/text()'))
into :new.postdate, :new.title, :new.company, :new.location
from dual;

end loop;
/

<?xml version="1.0" encoding="iso-8859-1">
<recordset>
<row>
<date><![CDATA[Jul 25]]></date>
<title><![CDATA[<a href="</code> http://jobsearch.monster.com:80/getjob.asp?JobID=27427955&AVSDM=2005%2D07%2D25+08%3A11%3A26&Logo=1&q=php&cy=US&sort=dt" >SENIOR
HTML/CSS/JAVASCRIPT DEVELOPER</a>]]></title>
<company><![CDATA[RCG Information Technology]]></company>
<location><![CDATA[<a onClick="popMMLL('FL','Orlando'); return false;" href="
http://jobsearch.monster.com:80/385" >FL-Orlando</a>]]></location>
<myfile><![CDATA[<a href="
http://my.monster.com/JobFile/JobFile.aspx?action=ADD&JobID=27427955&jobTitle=SENIOR+HTML%2FCSS%2FJAVASCRIPT+DEVELOPER&fjs=1&q=php&cy=US&sort=dt" ></a>]]></myfile> <code>
</row>
</recordset>

Nesting of loops to extract multiple tags

Raghu, April 10, 2006 - 3:56 pm UTC

Hi Tom , 
   Thanks for the wonderful service you provide. I am trying to parse the xml below to insert into multiple tables.  
- <LOAN_APPLICATION MISMOVersionID="2.3.1">
  <BORROWER BorrowerID="B001" JointAssetLiabilityReportingType="Jointly" _FirstName="Fred" _HomeTelephoneNumber="5551211111" _LastName="Flintstone" _PrintPositionType="Borrower" _SSN="111111111" _UnparsedName="Fred Flintstone" /> 
  <EMPLOYER CurrentEmploymentMonthsOnJob="1" CurrentEmploymentTimeInLineOfWorkYears="20" CurrentEmploymentYearsOnJob="15" EmploymentBorrowerSelfEmployedIndicator="N" EmploymentPositionDescription="Butcherb1" _City="Beverly Hills" _Name="Bedrock Quarry" _PostalCode="90210" _State="CA" _StreetAddress="100 Quartz Way" _TelephoneNumber="5551112121" /> 
  <EMPLOYER CurrentEmploymentMonthsOnJob="0" CurrentEmploymentTimeInLineOfWorkYears="5" CurrentEmploymentYearsOnJob="5" EmploymentBorrowerSelfEmployedIndicator="Y" EmploymentPositionDescription="Owner/Super Modelb1" _City="Beverly Hills" _Name="Taradacdyl Burgers" _PostalCode="90210" _State="CA" _StreetAddress="200 Model Way" _TelephoneNumber="5551112121" /> 
- <BORROWER BorrowerID="B002" JointAssetLiabilityReportingType="Jointly" _FirstName="Wilma" _HomeTelephoneNumber="5551211111" _LastName="Flintstone" _PrintPositionType="CoBorrower" _SSN="111111111" _UnparsedName="Wilma Flintstone">
  <_RESIDENCE BorrowerResidencyBasisType="Own" BorrowerResidencyDurationMonths="0" BorrowerResidencyDurationYears="5" BorrowerResidencyType="Current" _City="Beverly Hills" _PostalCode="90210" _State="CA" _StreetAddress="100 Front Street" /> 
  <_RESIDENCE BorrowerResidencyBasisType="Own" BorrowerResidencyDurationMonths="0" BorrowerResidencyDurationYears="5" BorrowerResidencyType="Current" _City="Beverly Hills" _PostalCode="90210" _State="CA" _StreetAddress="100 Front Street" /> 
  <CURRENT_INCOME IncomeType="Base" _MonthlyTotalAmount="10000.00" /> 
  <CURRENT_INCOME IncomeType="Base" _MonthlyTotalAmount="6000.00" /> 
  <DECLARATION AlimonyChildSupportObligationIndicator="N" BankruptcyIndicator="N" BorrowedDownPaymentIndicator="N" CitizenshipResidencyType="USCitizen" CoMakerEndorserOfNoteIndicator="N" HomeownerPastThreeYearsType="Yes" IntentToOccupyType="Yes" LoanForeclosureOrJudgementIndicator="N" OutstandingJudgementsIndicator="N" PartyToLawsuitIndicator="N" PresentlyDelinquentIndicator="N" PriorPropertyTitleType="JointWithSpouse" PriorPropertyUsageType="PrimaryResidence" PropertyForeclosedPastSevenYearsIndicator="N" /> 
  <EMPLOYER CurrentEmploymentMonthsOnJob="1" CurrentEmploymentTimeInLineOfWorkYears="20" CurrentEmploymentYearsOnJob="15" EmploymentBorrowerSelfEmployedIndicator="N" EmploymentPositionDescription="Butcher" _City="Beverly Hills" _Name="Bedrock Quarry" _PostalCode="90210" _State="CA" _StreetAddress="100 Quartz Way" _TelephoneNumber="5551112121" /> 
  <EMPLOYER CurrentEmploymentMonthsOnJob="0" CurrentEmploymentTimeInLineOfWorkYears="5" CurrentEmploymentYearsOnJob="5" EmploymentBorrowerSelfEmployedIndicator="Y" EmploymentPositionDescription="Owner/Super Model" _City="Beverly Hills" _Name="Taradacdyl Burgers" _PostalCode="90210" _State="CA" _StreetAddress="200 Model Way" _TelephoneNumber="5551112121" /> 
  </BORROWER>
  </LOAN_APPLICATION>

I am able to get the borrower information, using the table and XMlSequence combination. 

  Begin
    FOR Borrrow in
        ( select 
          extractvalue(value(i),'/BORROWER/@BorrowerID') Borrid
          FROM
              IMPORT p ,
              TABLE( xmlsequence( extract(xmltype(p.loanapp), '/LOAN_APPLICATION/BORROWER') ) ) i
           where id= p_id
        )
  Loop
   -- Insert into the tables here for individual values here

  End loop;
How do you use multiple nesting to insert the data pertaining to a particular borrower. I am unable to find a solution for this problem.


Declare 
l_xml xmltype;
begin 
for i in ( 
 select  rownum, 
  value(borr)   data ,  -- This should contain all the information for each borrowe Correct ??? 
 extractvalue( value(borr),'/BORROWER/@BorrowerID') ID 
 FROM
 PF_MINDBOXIMPORT p ,
 TABLE(XMLSEQUENCE(extract(xmltype(p.loanapp), '/LOAN_APPLICATION/BORROWER' ))) borr
 where p.id= 217 )
Loop 
   dbms_output.put_line( i.ID);
 /* here I need to loop again for any multiple tags for the borrower above  i.data is already a V array so why dosen't the code below fail*/
   for j in (  select extractvalue     (i.data,'/EMPLOYER/@EmploymentPositionDescription') desc  from dual  ) 
   Loop 
    -- Insert data for the particular borrower 
    dbms_output.put_line( i.desc );
   end loop;
end loop;
end;
/
SQL> /
 TABLE(XMLSEQUENCE(extract(xmltype(p.loanapp), '/LOAN_APPLICATION/BORROWER' ))) borr
   *
ERROR at line 10:
ORA-06550: line 14, column 84:
PL/SQL: ORA-00923: FROM keyword not found where expected
ORA-06550: line 14, column 13:
PL/SQL: SQL Statement ignored
ORA-06550: line 16, column 29:
PLS-00103: Encountered the symbol "DESC" when expecting one of the following:
<an identifier> <a double-quoted delimited-identifier> delete
exists prior <a single-quoted SQL string>
The symbol "<an identifier> was inserted before


I am trying various combinations of extract , extractvalue functions to get the individual xml segment to loop again for the employment ingformation and I'm unable to achieve 
it.
 
Your suggestions will be of great help.

Thanks in advance.
Raghu
 

How to extract this value

Rahul, November 23, 2006 - 1:37 pm UTC

was wondering if anyone can help me out or if there is a way to do this in xml.
I have a xml of the form -

<RESPONSE ResponseDateTime="2006-11-16T11:46:37">
<KEY _Name="CustomerNumber" _Value="7303881"/>
<KEY _Name="TransactionNumber" _Value="001010021"/>
<KEY _Name="Type" _Value="UNDERWRITING_RESPONSE1.1"/>
<KEY _Name="CompanyID" _Value="00006"/>
</RESPONSE>

I need to loop thru the KEY elements to parse the attributes whose Values depend
on the Name.
in other words -
when CustomerNumber then 7303881
when TransactionNumber then 001010021
when Type then RESPONSE
when CompanyID then 00006.

I started this out with, but doesn't seem to do anything-

declare
xml XMLTYPE;
v_node_name varchar2(60);
v_cust_nbr varchar2(60);
v_TransactionNumber varchar2(60);
v_Type varchar2(60);
v_CompanyID varchar2(60);

begin
loop
v_node_name := xml.extract('/RESPONSE/KEY/@_Name').getstringval();
case when v_node_name = 'LoanNumber' then
v_cust_nbr := xml.extract('/RESPONSE/KEY/@_Value').getstringval();
when v_node_name = 'TransactionNumber' then
v_TransactionNumber := xml.extract('/RESPONSE/KEY/@_Value').getstringval();
when v_node_name = 'Type' then
v_Type := xml.extract('/RESPONSE/KEY/@_Value').getstringval();
when v_node_name = 'CompanyID' then
v_CompanyID := xml.extract('/RESPONSE/KEY/@_Value').getstringval();
end case;
end loop;
end;




Search string from huge XMLNode

Bipin Ganar, August 28, 2007 - 9:24 am UTC

Hi Tom,

I have trillions of records in table with XMLType column. It contents some descriptive parts like news. Now I want to search particular string in the node, extract take very huge time (response time is high). Is it possible to search from the XML with very huge node?

e.g. Would like to search for test in below string, just example however the data will be huge in source.

<?xml version="1.0"?>
<Record>
<Type>UPDATE</Type>
<Source>I was interested in using the multi-table insert feature in 9i but am stumped by the
restriction that the subquery can't contain a sequence. I use a sequence to assign a
Primary Key in one of the tables that is the target of the multi-table insert. Can you
suggest a workaround? Will calling a user-defined function that returns the test nextval of
the sequence work in the subquery?
</Source>
<Instrument>NEWS</Instrument>
</Record>


<?xml version="1.0"?>
<Record>
<Type>UPDATE</Type>
<Source>What about the situtation where the targets of the multi-table insert have a sequence value in
common between them? In the following example, I'd like the s_id column value to be identical for
each row inserted into both tables:</Source>
<Instrument>NEWS</Instrument>
</Record>


<?xml version="1.0"?>
<Record>
<Type>UPDATE</Type>
<Source>You want to look into the XMLType in 9i R2. There are some cool features you
can use to accomplish what you want to do. XMLSEQUENCE is a cool feature that
will break down many nodes into individual xmltypes, and then the TABLE
function will turn those into rows. This will make sense in the code sample
below. Basically, I'd use a table to insert the XML document into, and then
have an on insert trigger manage breaking out the values</Source>
<Instrument>NEWS</Instrument>
</Record>

Urgent response ..........

Thanks in advance.
Tom Kyte
September 04, 2007 - 1:42 pm UTC

trillions eh...

yes, you can index XML - see the Oracle Text reference.

http://docs.oracle.com/docs/cd/B19306_01/appdev.102/b14259/xdb09sea.htm#sthref1186

xml

A reader, April 21, 2009 - 11:01 pm UTC


More to Explore

CLOB/BLOB/etc

Complete documentation on Securefiles and Large Objects here