Read Columns from XMLTable - oracle

I have the below xml in a column as CLOB. How to read the columns of the below XML using XMLTable. I need to retrieve the data for all the nodes. I have shown the nodes in the below.
<?xml version = "1.0" encoding = "UTF-8" standalone = "yes" ?>
<Supplier>
<Electronics>
<Vendor>
<PoductCode>APP13</PoductCode>
<Phones>
<Model>iPhone13</Model>
<Color>Silver</Color>
<Storage>128GB</Storage>
</Phones>
</Vendor>
<Vendor>
<PoductCode>APP13P</PoductCode>
<Phones>
<Model>iPhone13Pro</Model>
<Color>Grey</Color>
<Storage>512GB</Storage>
</Phones>
</Vendor>
<Manufacturer>Apple</Manufacturer>
</Electronics>
<Electronics>
<Vendor>
<PoductCode>SAMS22</PoductCode>
<Phones>
<Model>S22</Model>
<Color>Black</Color>
<Storage>256GB</Storage>
</Phones>
</Vendor>
<Vendor>
<PoductCode>SAMS23U</PoductCode>
<Phones>
<Model>S23 Ultra</Model>
<Color>Gold</Color>
<Storage>512GB</Storage>
</Phones>
</Vendor>
<Manufacturer>Samsung</Manufacturer>
</Electronics>
<SupplierName>AlphaLLC</SupplierName>
</Supplier>
ProdCode--Model--Color --Storage--Manufact--SupplierName
APP13 --iPhone13--Silver --128GB --Apple -- AlphaLLC
APP13P --iPhone13Pro --Grey --512GB --Apple -- AlphaLLC

See the below query. The only tricky part is using the ./ to get the ancestor values.
select poductcode, model, color, storage, Manufacturer, Supplier
from test_table t
cross join xmltable
(
'/Supplier/Electronics/Vendor'
passing xmltype(t.a_clob)
columns
PoductCode varchar2(4000) path 'PoductCode',
Model varchar2(4000) path 'Phones/Model',
Color varchar2(4000) path 'Phones/Color',
Storage varchar2(4000) path 'Phones/Storage',
Manufacturer varchar2(4000) path './../Manufacturer',
Supplier varchar2(4000) path './../../SupplierName'
) phones;

Related

how to use xmltable to read values from a clob?

I'm trying to get the values of the attributes from table MVR_DTL in column VENDOR_XML. VENDOR_XML is of datatype clob and contains an xml that looks like this
<?xml version="1.0" encoding="UTF-8"?>
<MVRCHPINFF_1.0>
<MVRRecLoop>
<CLoop>
<CRec>
<C_MVRNumberAddr>ROMAN GENERAL</C_MVRNumberAddr>
</CRec>
<CRec>
<C_MVRNumberAddr>ROMAN ST</C_MVRNumberAddr>
</CRec>
<CRec>
<C_MVRNumberAddr>ROMAN CITY, ROME 111111</C_MVRNumberAddr>
</CRec>
</CLoop>
</MVRRecLoop>
</MVRCHPINFF_1.0>
I tried running
SELECT c.Address
from MVR_DTL M, XMLTABLE('/MVRCHPINFF_1.0/MVRRecLoop/CLoop/CRec'
passing XMLTYPE(M.VENDOR_XML)
columns Address XMLTYPE PATH './C_MVRNumberAddr') c;
I'm expecting something like
ROMAN GENERAL ROMAN ST ROMAN CITY, ROME 111111
but i only get 'Statement has failed, however your database does not return any error information.'
Oracle version 12.2.0.1.0
SELECT c.Address from MVR_DTL M,
XMLTABLE(
'string-join(/MVRCHPINFF_1.0/MVRRecLoop/CLoop/CRec/C_MVRNumberAddr, " ")'
passing XMLTYPE(M.VENDOR_XML)
columns Address varchar2(200) PATH '.') c;

updating CLOB column with multiple namespace in Oracle

I am trying to update an element which is inside a clob column in oracle DB.
First challenge I am facing is that my clob xml has 2 namespaces and I am not able to get that working .
<?xml version="1.0"?>
<esbmsg:EsbMessage xmlns:esbmsg="http://www.test.com/esb/message/1.0">
<esbmsg:Body>
<Transaction xmlns="http://test.com">
<test-element>
<finalElement>false</finalElement>
</test-elemen>
</Transaction>
</esbmsg:Body>
</esbmsg:EsbMessage>
select x.* from cc_messagehistory y
cross join xmltable(
xmlnamespaces('http://www.test.com/esb/message/1.0' as "esbmsg",
'http://test.com ' ),
'/esbmsg:EsbMessage'
passing xmltype.createxml(y.payload)
factext varchar2(10) path '/esbmsg:EsbMessage/esbmsg:Body/Transaction/test-element/finalElement'
) x;
ORA-19102: XQuery string literal expected
19102. 00000 - "XQuery string literal expected"
*Cause: The string literal containing the XQuery expression was missing.
*Action: Specify the XQuery expression as a string literal. Error at Line: 64 Column: 99
The immediate cause of the ORA-01902 is that you missed the default keyword:
xmlnamespaces('http://www.test.com/esb/message/1.0' as "esbmsg",
default 'http://test.com'),
I've removed the extra space at the end of the URI, which would cause problems later. But you are also missing the columns keyword, and you can simplify the conversion of the CLOB value to an XMLType.
Putting that together, and with a CTE to supply your (corrected) sample XML:
-- CTE for sample data
with cc_messagehistory(payload) as (
select to_clob('<?xml version="1.0"?>
<esbmsg:EsbMessage xmlns:esbmsg="http://www.test.com/esb/message/1.0">
<esbmsg:Body>
<Transaction xmlns="http://test.com">
<test-element>
<finalElement>false</finalElement>
</test-element>
</Transaction>
</esbmsg:Body>
</esbmsg:EsbMessage>') from dual
)
-- actual query
select x.*
from cc_messagehistory y
cross join xmltable (
xmlnamespaces (
'http://www.test.com/esb/message/1.0' as "esbmsg",
default 'http://test.com'
),
'/esbmsg:EsbMessage'
passing xmltype(y.payload)
columns factext varchar2(10)
path '/esbmsg:EsbMessage/esbmsg:Body/Transaction/test-element/finalElement'
) x;
FACTEXT
----------
false
For the update you could do something like:
update cc_messagehistory y
set payload = XMLSerialize(document
XMLQuery('declare default element namespace "http://test.com"; (: :)
declare namespace esbmsg="http://www.test.com/esb/message/1.0"; (: :)
copy $i := $xml modify (
for $j in $i//esbmsg:EsbMessage/esbmsg:Body/Transaction/test-element/finalElement
return replace value of node $j with $new
)
return $i'
passing xmltype(y.payload) as "xml",
'true' AS "new"
returning content
)
indent size=2
)
where xmlexists('declare default element namespace "http://test.com"; (: :)
declare namespace esbmsg="http://www.test.com/esb/message/1.0"; (: :)
$xml//esbmsg:EsbMessage/esbmsg:Body/Transaction/test-element/finalElement[text()="false"]'
passing xmltype(y.payload) as "xml");
which transforms that source CLOB into:
<?xml version="1.0"?>
<esbmsg:EsbMessage xmlns:esbmsg="http://www.test.com/esb/message/1.0">
<esbmsg:Body>
<Transaction xmlns="http://test.com">
<test-element>
<finalElement>true</finalElement>
</test-element>
</Transaction>
</esbmsg:Body>
</esbmsg:EsbMessage>
db<>fiddle (works on 18c; errors on 11gR2, but patch levels may make a difference; also tested successfully elsewhere on 12cR1)

read the XML type column using stored procedure

How to display parent tags and attributes from XML TYPE column using stored procedure?
Example: I have below data in XMLTYPE Column in one table:
<Employee>
<Employee_information >
<Employee_content>
<task>
<Employee_stem>
<Employee_stem_paragraph>fsdbnfjksdflsdj.</Employee_stem_paragraph>
<Employee_stem_paragraph>dsfsdfsdfsdf</Employee_stem_paragraph>
</Employee_stem>
<Employee_response>
<Employee_response_choices>
<Employee_choice_list>
<Employee_block_choice numeric_identifier="1">
<Employee_choice_paragraph>sdfsdfsdfsdf</Employee_choice_paragraph>
</Employee_block_choice>
</Employee_choice_list>
</Employee_response_choices>
</Employee>
Output: display all the parent tags and attributes in it.
Output example:
Employee,Employee_information,Employee_content,Employee_stem,Employee_stem_paragraph,Employee_response,Employee_response_choices,Employee_choice_list,Employee_block_choice,
numeric_identifier,Employee_choice_paragraph.
In general you have to fix you xml. All tag have to be closed.
1-st select //*/name(.) - extract only element's name.
2-en select '//*/name(#*) -extract only attributes' name.
select *
from xmltable('//*/name(.)'
passing xmltype('<Employee>
<Employee_information>
<Employee_content>
<task>
<Employee_stem>
<Employee_stem_paragraph>fsdbnfjksdflsdj.</Employee_stem_paragraph>
<Employee_stem_paragraph>dsfsdfsdfsdf</Employee_stem_paragraph>
</Employee_stem>
<Employee_response>
<Employee_response_choices>
<Employee_choice_list>
<Employee_block_choice numeric_identifier="1">
<Employee_choice_paragraph>sdfsdfsdfsdf</Employee_choice_paragraph>
</Employee_block_choice>
</Employee_choice_list>
</Employee_response_choices>
</Employee_response>
</task>
</Employee_content>
</Employee_information>
</Employee>') columns name varchar2(200) path '.' )
union all
select *
from xmltable('//*/name(#*)'
passing xmltype('<Employee>
<Employee_information>
<Employee_content>
<task>
<Employee_stem>
<Employee_stem_paragraph>fsdbnfjksdflsdj.</Employee_stem_paragraph>
<Employee_stem_paragraph>dsfsdfsdfsdf</Employee_stem_paragraph>
</Employee_stem>
<Employee_response>
<Employee_response_choices>
<Employee_choice_list>
<Employee_block_choice numeric_identifier="1">
<Employee_choice_paragraph>sdfsdfsdfsdf</Employee_choice_paragraph>
</Employee_block_choice>
</Employee_choice_list>
</Employee_response_choices>
</Employee_response>
</task>
</Employee_content>
</Employee_information>
</Employee>') columns name varchar2(200) path '.' )

Oracle DB - Extract XML data using XMLTABLE

I am using XMLTABLE Function in Oracle 10g database and want to extract values from XML into Oracle Table.
SELECT *
FROM xmltable(
xmlnamespaces ('http://www.cool.com/totem/1.1' AS "n1"), '/n1:totem/n1:results'
PASSING xmltype.createxml(('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<totem xmlns="http://www.cool.com/totem/1.1">
<results>
<valuationDate>2014-07-31</valuationDate>
<clientID>220</clientID>
<energy>
<underlier>
<name>CO2 CER</name>
<group>European Emissions</group>
<units>EUR / MT</units>
<pricingTime>LDN 17:00</pricingTime>
<instrument>
<period>Month</period>
<startDate>2014-12-01</startDate>
<endDate>2014-12-31</endDate>
<type>Forward</type>
<price>0.25852</price>
<priceOut>r</priceOut>
<contributors>15</contributors>
</instrument>
</underlier>
<underlier>
<name>CO2 CER</name>
<group>European Emissions</group>
<units>EUR / MT</units>
<pricingTime>LDN 17:00</pricingTime>
<instrument>
<period>Month</period>
<startDate>2014-12-01</startDate>
<endDate>2014-12-31</endDate>
<type>Forward</type>
<price>0.25852</price>
<priceOut>r</priceOut>
<contributors>15</contributors>
</instrument>
</underlier>
</energy>
</results>
</totem>'
))
COLUMNS valuationDate varchar2(500) PATH 'n1:valuationDate',
clientID varchar2(500) PATH 'n1:clientID',
name varchar2(500) PATH 'n1:energy/n1:underlier/n1:name',
group1 varchar2(500) PATH 'n1:energy/n1:underlier/n1:group',
units varchar2(500) PATH 'n1:energy/n1:underlier/n1:units',
pricingTime varchar2(500) PATH 'n1:energy/n1:underlier/n1:pricingTime',
period varchar2(500) PATH 'n1:energy/n1:underlier/n1:instrument/n1:period',
startDate varchar2(500) PATH 'n1:energy/n1:underlier/n1:instrument/n1:startDate',
endDate varchar2(500) PATH 'n1:energy/n1:underlier/n1:instrument/n1:endDate',
type varchar2(500) PATH 'n1:energy/n1:underlier/n1:instrument/n1:type',
price varchar2(500) PATH 'n1:energy/n1:underlier/n1:instrument/n1:price',
priceOut varchar2(500) PATH 'n1:energy/n1:underlier/n1:instrument/n1:priceOut',
contributors varchar2(500) PATH 'n1:energy/n1:underlier/n1:instrument/n1:contributors'
) AS instrument
o/p is:
XMLNLS_NS VALUATIONDATE CLIENTID NAME GROUP1 PERIOD STARTDATE ENDDATE TYPE PRICE PRICEOUT CONTRIBUTORS
2014-07-31 220
How can I extract/populate values for rest of the tags ?
Edit: Thanks.
But when I have more than one underliner, I get following
error ORA-19279: XPTY0004 - XQuery dynamic type mismatch: expected singleton sequence - got multi-item sequence
Use the correct namespace. Namespaces are inherited, so basically all your elements here are in the http://www.cool.com/totem/1.1 namespace. For example,
n1:results/energy/underlier/name
should be
n1:results/n1:energy/n1:underlier/n1:name

Oracle XMLTable functions and XPATH

I have a following xml document stored in XML type table
<?xml version="1.0" encoding="utf-8"?>
<Document xmlns="urn:iso:std:iso:200:tech:xsd:101" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<FIToFICstmrCdtTrf xmlns="urn:iso:std:iso:200:tech:xsd:101">
<CreditTx>
<PaymentID>
<InstrumentId>AAB000001</InstrumentId>
<Id>4730 2013-10-23 AAB000001</Id>
<TranxId>BULKTTXTDAAB000001</TranxId>
</PaymentID>
</CreditTx>
</FIToFICstmrCdtTrf>
</Document>
When i execute the below SQL
SELECT payments.instrumentid,
payments.id,
payments.tranxid
FROM paymentxml,
XMLTable('for $i in /Document/FIToFICstmrCdtTrf/CreditTx/PaymentID
return $i'
PASSING OBJECT_VALUE
COLUMNS
instrumentid VARCHAR2(20) PATH 'InstrumentId' ,
id VARCHAR2(20) PATH 'Id' ,
tranxid VARCHAR2(20) PATH 'TranxId'
)payments
I get no results even though the xpath is correct any ideas what am i missing
For the
for $i in /Document/FIToFICstmrCdtTrf/CreditTx/PaymentID return $i
part you must give the doc as
for $i in
doc("/your/path/your.xml")/Document/FIToFICstmrCdtTrf/CreditTx/PaymentID
return $i
it is important to know resources' location which is /your/path/your.xml
i hope this helps you.

Resources