updating CLOB column with multiple namespace in Oracle - 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)

Related

oracle xml parsing with multi rows

query from xml not return rows.
I running this query but not return rows.
The my xml is :
<?xml version="1.0" encoding="UTF-8"?>
<ns0:testata xmlns:ns0="http://siete">
<ns0:product>
<ns0:YEAR>2019</ns0:YEAR>
<ns0:PERIOD>1</ns0:PERIOD>
</ns0:product>
<ns0:product>
<ns0:YEAR>2019</ns0:YEAR>
<ns0:PERIOD>2</ns0:PERIOD>
</ns0:product>
</ns0:testata>
My query is
FROM XMLTABLE('/testata/product'
PASSING
(select xmltype(t.XML1) doc
from tb_test t)
COLUMNS
name varchar2(4) PATH './YEAR'
) xmlt
0 rows
please help me
Your XML document has a namespace, so you either need to wildcard the nodes in your XMLTable call, or - preferably - supply the same namespace information and prefixes:
-- CTE for sample data
with tb_test (xml1) as (select '<?xml version="1.0" encoding="UTF-8"?>
<ns0:testata xmlns:ns0="http://siete">
<ns0:product>
<ns0:YEAR>2019</ns0:YEAR>
<ns0:PERIOD>1</ns0:PERIOD>
</ns0:product>
<ns0:product>
<ns0:YEAR>2019</ns0:YEAR>
<ns0:PERIOD>2</ns0:PERIOD>
</ns0:product>
</ns0:testata>' from dual
)
-- actual query
select x.year
from tb_test t
cross join xmltable(
xmlnamespaces('http://siete' as "ns0"),
'/ns0:testata/ns0:product'
passing xmltype(t.xml1)
columns year number path 'ns0:YEAR'
) x;
YEAR
----------
2019
2019

Oracle XMLTABLE namespace issue

I am trying to get envelope_id as 80621b17-97a8-926d945b602a from the below XML through this script, but nothing comes out. Can any one have any idea ?
SELECT b.EnvelopeID
FROM sample_xml a,
XMLTABLE(xmlnamespaces('http://www.w3.org/2001/XMLSchema' as "xsd_k",
'http://www.w3.org/2001/XMLSchema-instance' AS "xsi",
'http://www.docusign.net/API/3.0' AS "k"),
'/xsd_k:DocuSignEnvelopeInformation/xsd_k:EnvelopeStatus' PASSING a.xml
COLUMNS EnvelopeID VARCHAR2(200) PATH 'EnvelopeID')b;
My sample xml is :
<DocuSignEnvelopeInformation xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.docgign.net/API/3.0">
<EnvelopeStatus>
<EnvelopeID>80621b17-97a8-926d945b602a</EnvelopeID>
</EnvelopeStatus>
</DocuSignEnvelopeInformation>
You can use the default namespace. Just say 'default' :). And look to be the same as in your XML document:
SELECT b.EnvelopeID
FROM (SELECT xmltype ('
<DocuSignEnvelopeInformation xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.docgign.net/API/3.0">
<EnvelopeStatus>
<EnvelopeID>80621b17-97a8-926d945b602a</EnvelopeID>
</EnvelopeStatus>
</DocuSignEnvelopeInformation>') AS xml FROM DUAL) a,
XMLTABLE(xmlnamespaces(default 'http://www.docgign.net/API/3.0'),
'/DocuSignEnvelopeInformation/EnvelopeStatus' PASSING a.xml
COLUMNS EnvelopeID VARCHAR2(200) PATH 'EnvelopeID')b;
We can also repair your variant. First you have 'docgign' instead of 'docusign' in the xml document. Repair one of the both. Than change '/xsd_k:DocuSignEnvelopeInformation/xsd_k:EnvelopeStatus' with '/k:DocuSignEnvelopeInformation/k:EnvelopeStatus', because this is the default namespace and at last change 'EnvelopeID' with 'k:EnvelopeID' :
SELECT EnvelopeID
FROM (SELECT xmltype ('
<DocuSignEnvelopeInformation xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.docusign.net/API/3.0">
<EnvelopeStatus>
<EnvelopeID>80621b17-97a8-926d945b602a</EnvelopeID>
</EnvelopeStatus>
</DocuSignEnvelopeInformation>') AS xml FROM DUAL) a,
XMLTABLE(xmlnamespaces('http://www.w3.org/2001/XMLSchema' as "xsd_k",
'http://www.w3.org/2001/XMLSchema-instance' AS "xsi",
'http://www.docusign.net/API/3.0' AS "k"),
'/k:DocuSignEnvelopeInformation/k:EnvelopeStatus' PASSING a.xml
COLUMNS EnvelopeID VARCHAR2(200) PATH 'k:EnvelopeID')b;
See HERE(search for Default Namespace)
When a default namespace declaration is used on an element, all
unqualified element names within its scope are automatically
associated with the specified namespace identifier.
That is the reason because DocuSignEnvelopeInformation and all other nodes under this have the namespace xmlns="http://www.docusign.net/API/3.0". If this namespace was not defined, the nodes would be without namespace and you wouldn't need to use namespace in xmltable.

Oracle xmltable query / ORA-19279: XPTY0004 - XQuery dynamic type mismatch: expected singleton

I have this query :
SELECT TYPE, IDVIEW, ATTRIBUTE, VALUE
FROM XML_IMPORT_REPOSITORY t
CROSS JOIN XMLTABLE ('for $item in /SRDBSW/OBJ_DF[#IdView="ICU-ASW"]/*[#IdView]
for $item_attr in $item/#*
return element {$item/name(.)}
{
element idview {$item/#IdView/string()},
element attr {$item_attr/local-name(.)},
element value {$item_attr/string()}
}
' PASSING t.XMLDATA COLUMNS
TYPE VARCHAR2(30) PATH 'local-name(.)',
IDVIEW VARCHAR2(30) PATH 'idview',
attribute VARCHAR2(30) PATH 'attr',
value VARCHAR2(30) PATH 'value' ) x
I´m getting this error :
ORA-19279: XPTY0004 - XQuery dynamic type mismatch: expected singleton
sequence - got multi-item sequence
19279. 00000 - "XPTY0004 - XQuery dynamic type mismatch: expected singleton sequence - got multi-item sequence"
I found the problem , the problem is this line :
element value {$item_attr/string()}
But can´t find a workaround to get the value of the attribute ...
where a sample off the xml
<OBJ_DF IdView="ICU-ASW" CategoryFlag="0" OwnerFlag="0" ObjLevel="Element" IsDefined="Y" ShortDescription="CONFIG Major function" ShortDescriptionCore="CONFIG Major function" LongDescription="CONFIG Major function Manual Load" Mnemonic="CONFIG Major function">
<TEXTUAL_CURVE_DF IdView="0001" ShortDescription="PhysSide octet" ShortDescriptionCore="PhysSide octet" LongDescription="Type identifying the physical side of a unit in 8 bits" Mnemonic="Physical_Side_Octet_T" CategoryFlag="0" OwnerFlag="0" IsDirect="Y" Type="CURVE" CurveType="Textual" RawFormat="Unsigned Integer">
<DIG_POINT_LIST>
<DIG_POINT LowValue="0" StatusText="SIDE_1" Mnemonic="Side_1" Ldesc="FCI/Config/Physical_Side_Octet.Side_1" HighValue="0"/>
<DIG_POINT LowValue="1" StatusText="SIDE_2" Mnemonic="Side_2" Ldesc="FCI/Config/Physical_Side_Octet.Side_2" HighValue="1"/>
</DIG_POINT_LIST>
</TEXTUAL_CURVE_DF>
<TEXTUAL_CURVE_DF IdView="0002" ShortDescription="Health_T" ShortDescriptionCore="Health_T" LongDescription="Type for Health of unit or equipment" Mnemonic="Health_T" CategoryFlag="0" OwnerFlag="0" IsDirect="Y" Type="CURVE" CurveType="Textual" RawFormat="Unsigned Integer">
<DIG_POINT_LIST>
<DIG_POINT LowValue="0" StatusText="UNHEALTHY" Mnemonic="Unhealthy" Ldesc="FCI/Config/Health.Unhealthy" HighValue="0"/>
<DIG_POINT LowValue="1" StatusText="HEALTHY" Mnemonic="Healthy" Ldesc="FCI/Config/Health.Healthy" HighValue="1"/>
</DIG_POINT_LIST>
</TEXTUAL_CURVE_DF>
<TEXTUAL_CURVE_DF IdView="0003" ShortDescription="Logical_Power_T" ShortDescriptionCore="Logical_Power_T" LongDescription="Type for Logical On or Off status of unit or equipment" Mnemonic="Logical_Power_T" CategoryFlag="0" OwnerFlag="0" IsDirect="Y" Type="CURVE" CurveType="Textual" RawFormat="Unsigned Integer">
<DIG_POINT_LIST>
<DIG_POINT LowValue="0" StatusText="OFF" Mnemonic="Off" Ldesc="FCI/Config/Logical_Power.Off" HighValue="0"/>
<DIG_POINT LowValue="1" StatusText="ON" Mnemonic="On" Ldesc="FCI/Config/Logical_Power.On" HighValue="1"/>
</DIG_POINT_LIST>
</TEXTUAL_CURVE_DF>
</OBJ_DF>
the query shoud return the name of the items and all is attribues
the working set is :
CREATE OR REPLACE directory XTDIR AS 'C:\Users\aadr\Documents\SCCOPEN\NEW-IMPORT\demo';
BEGIN
DBMS_XMLSCHEMA.registerSchema(
SCHEMAURL => 'http://www.w3.org/2001/XMLSchema',
SCHEMADOC => bfilename('XTDIR','SRDBSW_schema_full.xsd'));
END;
CREATE TABLE XML_IMPORT_REPOSITORY (xmlkey VARCHAR(20) PRIMARY KEY, xmlData XMLType)
xmltype column xmlData XMLSCHEMA "http://www.w3.org/2001/XMLSchema"
element "SRDBSW" tablespace USERS;
INSERT INTO XML_IMPORT_REPOSITORY(XMLKEY, XMLDATA) VALUES
('full',XMLType(bfilename('XTDIR', 'full.xml'), nls_charset_id('AL32UTF8')));
commit;
with all of this is not working , the reason I´m doing this is to increase preformace on the query whitout this the query is very slow whit large xmls files
This looks like bug 13060499, which is related to 7554407; see My Oracle Support doc ID 1373311.1. There isn't much info though. It's known to affect 11.2.0.2 but it isn't clear if or when it was fixed - I don't see the issue in 11.2.0.3 so it may have been quietly fixed in that patch set.
A workaround seems to be to add what should be a redundant index to the attribute reference:
element value {$item_attr[1]/string()}
But as that on its own doesn't seem to help, perhaps add it to everything:
SELECT TYPE, IDVIEW, ATTRIBUTE, VALUE
FROM XML_IMPORT_REPOSITORY t
CROSS JOIN XMLTABLE ('for $item in /SRDBSW/OBJ_DF[#IdView="ICU-ASW"]/*[#IdView]
for $item_attr in $item[1]/#*
return element {$item[1]/name(.)}
{
element idview {$item[1]/#IdView[1]/string()},
element attr {$item_attr[1]/local-name(.)},
element value {$item_attr[1]/string()}
}
' PASSING t.XMLDATA COLUMNS
TYPE VARCHAR2(30) PATH 'local-name(.)',
IDVIEW VARCHAR2(30) PATH 'idview',
attribute VARCHAR2(30) PATH 'attr',
value VARCHAR2(30) PATH 'value' ) x;
In 11.2.0.3 that gives the same result as not having the node index. I don't have an 11.2.0.2 instance to verify it on though (and SQL Fiddle, which is that version, fails without a helpful message).
You can also do this with a single for in the XQuery, by going straight to attribute level and then referring to the parent node with ../:
SELECT TYPE, IDVIEW, ATTRIBUTE, VALUE
FROM XML_IMPORT_REPOSITORY t
CROSS JOIN XMLTABLE ('for $item_attr in
/SRDBSW/OBJ_DF[#IdView="ICU-ASW"]/*[#IdView]/#*
return element {$item_attr[1]/../name(.)}
{
element idview {$item_attr[1]/../#IdView[1]/string()},
element attr {$item_attr[1]/local-name(.)},
element value {$item_attr[1]/string()}
}'
PASSING t.XMLDATA
COLUMNS
TYPE VARCHAR2(30) PATH 'local-name(.)',
IDVIEW VARCHAR2(30) PATH 'idview',
attribute VARCHAR2(30) PATH 'attr',
value VARCHAR2(30) PATH 'value' ) x;
I've left the [1] in just in case that is still helpful/needed. But SQL Fiddle now works with and without them, which is rather more promising.
SELECT x.* FROM XML_IMPORT_REPOSITORY t
CROSS JOIN XMLTABLE ('/SRDBSW/OBJ_DF/*[/SRDBSW/OBJ_DF/#IdView="ICU-ASW"]'
PASSING t.XMLDATA
COLUMNS IdView VARCHAR2(30) PATH '#IdView',
attr_name VARCHAR2(30) PATH 'local-name(.)') x
union all
SELECT z.* FROM XML_IMPORT_REPOSITORY tt
CROSS JOIN XMLTABLE ('/SRDBSW/OBJ_DF/*[/SRDBSW/OBJ_DF/#IdView="ICU-ASW"]/#*'
PASSING tt.XMLDATA
COLUMNS
attr_name VARCHAR2(30) PATH 'local-name(.)',
attr_value VARCHAR2(30) PATH '.') z
this is all must good for me ... if I find a way ( if there is one ) to separate "data" from the two query ...

Reading xml using Oracle

We have to read a xml using pl/sql. The top few lines of the xml are pasted below. In the xml, for one Node,there is one Equipment. For one Equipment, there are multiple Cabinet. For one Cabinet there are multiple Subrack & for one Subrack there are multiple Boards.
We have developed a below query to parse.
Step-1:
create table emp_xml of xmltype xmltype store as securefile binary xml;
Step-2:
insert into emp_xml values (xmltype(bfilename('XML_DIR','ahm_2015_04_01_172428.xml'), nls_charset_id('AL32UTF8') ));
Step-3:
select * from emp_xml;
Step-4:
select x.*
from emp_xml t,
xmltable(xmlnamespaces(default 'http://www.ericsson.com/axe/export/hw'(http :/ /
www.ericsson.com / axe /
export /
hw%27)),
'/NetworkInventory/Node' passing t.object_value columns
SiteName varchar2(10) path '#Name',
SiteType varchar2(10) path '#Type',
BuildingPractice varchar2(10) path
'//Equipment/#BuildingPractice') x;
This query is working perfectly.But when I am trying to fetch the Cabinet or Subrack details, we are getting below error.
ORA-19279: XPTY0004 - XQuery dynamic type mismatch: expected singleton sequence - got multi-item sequence
ORA-06512: at line 33
19279. 00000 - "XQuery dynamic type mismatch: expected singleton sequence - got multi- item sequence"
*Cause: The XQuery sequence passed in had more than one item.
*Action: Correct the XQuery expression to return a single item sequence.
Top Few Line of XML is given below.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<NetworkInventory xmlns="http://www.ericsson.com/axe/export/hw" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ericsson.com/axe/export/hw file:/opt/ericsson/nms_smo_srv/etc/export.xsd">
<Description>AXE HARDWARE INVENTORY DATA</Description>
<ExportDateTime Date="2015-04-01" Time="17:24:28"/>
<Node AdjustDate="2015-03-21" FunctionType=" " Name="BSC20" Site=" " Type="AXE" UserLabel="">
<Equipment BuildingPractice="BYB501">
<Cabinet Position="CabNumber=1">
<Subrack Name="FAN-1" Position="X=3,Y=2" Type="CP">
<Board Name=" " SlotPosition="255" Type="CP">
<ProductData FirstOperationDate="2013-11-20" LastChangedDate="2013-11-20" ManufacturedDate=" " ProductName=" " ProductNumber=" " ProductRevision=" " SerialNumber=" " Supplier="Ericsson AB"/>
</Board>
<Board Name=" " SlotPosition="255" Type="CP">
<ProductData FirstOperationDate="2013-11-20" LastChangedDate="2013-11-20" ManufacturedDate=" " ProductName=" " ProductNumber=" " ProductRevision=" " SerialNumber=" " Supplier="Ericsson AB"/>
</Board>
</Subrack>
Because your Cabinet is set not a single iterate.
When you want to present repeating groups in relational format, you have to extract the sequence of items in the main XQuery expression.
Each item is then passed to the COLUMNS clause to be further shredded into columns.
You're trying to expand a construct that's sort of similar to nested tables. Your Equipment node can have multiple Cabinets, so to extract details from those you need to pass those to a second XMLTable:
select x.SiteName, x.SiteType, x.BuildingPractice, y.Position
from emp_xml t
cross join xmltable(
xmlnamespaces(default 'http://www.ericsson.com/axe/export/hw'),
'/NetworkInventory/Node' passing t.object_value columns
SiteName varchar2(10) path '#Name',
SiteType varchar2(10) path '#Type',
BuildingPractice varchar2(10) path 'Equipment/#BuildingPractice',
Equipment XMLType path 'Equipment'
) x
cross join xmltable(
xmlnamespaces(default 'http://www.ericsson.com/axe/export/hw'),
'//Cabinet' passing x.Equipment columns
Position varchar2(15) path '#Position'
) y;
SITENAME SITETYPE BUILDINGPRACTICE POSITION
---------- ---------- ---------------- ---------------
BSC20 AXE BYB501 CabNumber=1
To get the the SubRack data too, you'd need to pass that out to a third level of XMLTable, etc.

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