简体   繁体   中英

Trying to extract a value from an xmltype but no value returned

This is my oracle SQL :

WITH q1(Tdata,paymentinterchangekey) AS
(
  SELECT XMLtype(transportdata, 1), paymentinterchangekey
    FROM bph_owner.paymentinterchange
   WHERE paymentinterchangekey = '137630105'
)
SELECT EXTRACT(q1.Tdata, '/Document/CstmrCdtTrfInitn/GrpHdr/MsgId'),
       q1.Tdata,
       q1.paymentinterchangekey "EE",
       q1.paymentinterchangekey "EE"
  FROM q1;

and data is :

<?xml version="1.0" encoding="ISO-8859-1"?>
<Document xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03 pain.001.001.03.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03" > 
<CstmrCdtTrfInitn>
<GrpHdr>
<MsgId>SEPA21012022</MsgId>
<CreDtTm>2022-01-20T11:45:59.177</CreDtTm>
<NbOfTxs>12</NbOfTxs>
<CtrlSum>22277.57</CtrlSum>
<InitgPty>
<Nm>

Any idea why the EXTRACT value is empty?

EXTRACT is deprecated. Use XMLQUERY and declare the namespace:

with q1 ( Tdata, paymentinterchangekey) AS (
  SELECT XMLtype(transportdata),
         paymentinterchangekey 
  from   bph_owner.paymentinterchange 
  where  paymentinterchangekey = '137630105'
)
select XMLQUERY(
         'declare default element namespace "urn:iso:std:iso:20022:tech:xsd:pain.001.001.03";
         /Document/CstmrCdtTrfInitn/GrpHdr/MsgId/text()'
         PASSING q1.Tdata
         RETURNING CONTENT
       ) AS msgid,
       q1.Tdata,
       q1.paymentinterchangekey "EE" 
from   q1;

db<>fiddle here

Ignoring the malformed XML, the issue is that your Document node declares a namespace, which you are not including; so you would need to do:

EXTRACT(q1.Tdata, '/Document/CstmrCdtTrfInitn/GrpHdr/MsgId',
  'xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03"')

which would give you

<MsgId xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">SEPA21012022</MsgId>

Presumably you only want the actual value, not the whole node, so you could do:

EXTRACT(q1.Tdata, '/Document/CstmrCdtTrfInitn/GrpHdr/MsgId/text()',
  'xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03"')

to get

SEPA21012022

However, the EXTRACT() function is deprecated , and has been for a long time, so you should use XMLQuery instead:

with q1 (Tdata) as (
  SELECT XMLtype(transportdata,1) from paymentinterchange
)
select XMLQuery('
    declare default element namespace "urn:iso:std:iso:20022:tech:xsd:pain.001.001.03";
    /Document/CstmrCdtTrfInitn/GrpHdr/MsgId/text()'
  passing Tdata
  returning content).getstringval()
from q1

db<>fiddle

If you want multiple values from the same XML then look at XMLTable.


So I have now run this as a generic SQL but get the following error : ORA-31011: XML parsing failed ORA-19202: Error occurred in XML processing LPX-00216: invalid character 195 (0xC3) Error at line 150 ORA-06512: at "SYS.XMLTYPE", line 283 ORA-06512: at line 1 Is there a way to 'skip' malformed rows?

The rows aren't malformed. The XML declaration says the encoding is ISO-8859-1, which allows any 'Latin-1 (Western)' characters, such as à - which is encoded as 0xC3 . Your XML is stored as a BLOB, which you are converting to XMLType. But as part of that conversion you are passing 1 as the csid value . That represents ASCII (or US7ASCII in Oracle). So the conversion is only expecting ASCII characters, and is complaining about anything else.

The Oracle character set name corresponding to ISO-8859-1 is WE8ISO8859P1 , so you need to supply the character set ID for that instead:

with q1 (Tdata) as (
  SELECT XMLtype(transportdata, nls_charset_id('WE8ISO8859P1')) from paymentinterchange
)
...

db<>fiddle showing the same error you are getting and the successful query with the correct character set.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM