Skip to Main Content

Breadcrumb

Connor and Chris will both be at AI World from October 12 to October 17 , the premier Oracle conference of 2025. If you're in Vegas, please come say Hi or pop into our sessions

Question and Answer

Chris Saxon

Thanks for the question, M. Ogun.

Asked: January 09, 2020 - 1:52 pm UTC

Last updated: January 10, 2020 - 9:44 am UTC

Version: 19

Viewed 1000+ times

You Asked

Hi,

I am trying to parse an xml response that has multiple child nodes.

It's something like:

<List>
  <Status>ACK</Status>
  <Status>ACK</Status>
  <Status>NACK</Status>
</List>


I was able to extract one line at a time. But I need to get all of them at once and store in apex_collections.

So I tried these (possibly not-so-wise) things:

- declare the xpath with an anchor
l_xpath_anchor varchar2(100) := '//List[~]/Status/text()';


- create a loop and replace ~ with consecutive numbers, starting from 1 obviously. Then in the same loop call the parse_xml API:

select apex_web_service.parse_xml_clob(
                         p_xml => env,
    p_xpath => l_xpath_anchor,
    p_ns => l_xmlns)
into l_foo
from (select xmltype(service_response) env from xml_master where tx_id = 202001071406422305841 and tx_uid = 413);
l_xpath := replace(l_xpath, '~', i);
dbms_output.put_line (l_foo||'  i: '||i);


This actually worked for a sample data like above. It has 3 child nodes and I knew it had to loop 3 times.
But I can never it on original data.

Is there a way to know how many child node does a parent node have so I can be sure about how many time should it loop?

and Chris said...

If you're trying to pull out all the Status values, passing the document to XMLTable seems a better way to me.

With this you can convert the XML to relational rows-and-columns:

with x as (
  select xmltype ( '<List>
  <Status>ACK</Status>
  <Status>ACK</Status>
  <Status>NACK</Status>
</List>' ) doc
  from  dual
)
  select xt.* from x, xmltable (
    '/List/Status'
    passing x.doc 
    columns  
      status varchar2(10) path '//text()'
  ) xt;

STATUS   
ACK       
ACK       
NACK    

Rating

  (1 rating)

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

Comments

swift response

Ogun, January 10, 2020 - 7:52 am UTC

Hi,

Thank you very much.

While I was waiting for an answer, I kept trying some other things.

I am not sure if this is a smart approach but I tried to catch
"/>" 
and count it by using
regexp_count 
against the xml response of my envelope. Then I created my loop for that number.

Would you say it's a bad idea? Should I stick with
xmltable()
?

Thank you again,

Have a great weekend.
Chris Saxon
January 10, 2020 - 9:44 am UTC

I'm not clear exactly what you're doing after extracting the values. But as a general principle for data processing:

Loops => SLOW
One SQL statement => FAST

So I'd lean towards using XMLTable to get the data you want. But really it depends on what you're doing next with these values.

I tried to catch "/>"

Sounds risky to me. What the response changes to include extra attributes? You'll be looping more than needed.

More to Explore

SQL

The Oracle documentation contains a complete SQL reference.