简体   繁体   中英

Retrieving XML elements from XMLType Oracle

Can someone help me with retrieving the data from XMLType column in Oracle?

drop table xml_analysis;
create table xml_analysis(id number,soft_attributes XMLType);
create table xml_softattributes(id number,soft_attributes varchar2(200));
INSERT INTO xml_analysis VALUES 
   (       1, XMLType(
              '<softattributes> 
               <attr1>ABC</attr1>
               <attr2>XYZ</attr2> 
               <attr3>PQR</attr3> 
               </softattributes>
                '));
   insert into xml_softattributes values(1,'attr1');
   insert into xml_softattributes values(1,'attr2');
   insert into xml_softattributes values(1,'attr3');
  1. Table xml_analysis contains the xmltype column ,whose attributes i don't know
  2. Table xml_softattributes contains list of softattributes (not the xpath),which are present in the xmltype column of the xml_analysis table
  3. Tables are joined based on id

Now my issue is to retrieve data from the xml_analysis table dynamically using a table xml_softattributes,how can i do that ?

Output required

Softattribute Value 
=======================  
   attr1        ABC
   attr2        XYZ
   attr3        PQR

Possible solution i can think of is using a dynamic string and execute ,but i don't want a dynamic string query to retrieve the data .

You can use the combination of existsNode and extract functions as follows.

SELECT b.SOFT_ATTRIBUTES,
  CASE
    WHEN existsNode (a.soft_attributes ,'/*/'
      ||b.SOFT_ATTRIBUTES) = 1
    THEN a.soft_attributes.extract('/*/'
      ||b.SOFT_ATTRIBUTES
      ||'/text()').getStringVal()
  END value
FROM xml_analysis a,
  xml_softattributes b
WHERE a.id = b.id;

* is Used as a wildcard to match any child node. For example, /PO/*/STREET matches any street element that is a grandchild of the PO element.

Output:

attr1   ABC
attr2   XYZ
attr3   PQR

If the set of attributes is fixed ( 'attr1', 'attr2', 'attr3' ), then you can extract the data from the XML structure and then unpivot. Then you can join to the other table in the usual way.

select id, softattribute, value
from (
       select x.id, xt.attr1, xt.attr2, xt.attr3
       from   xml_analysis x,
              xmltable('/softattributes'
                passing x.soft_attributes
                columns
                  attr1 varchar2(100) path 'attr1',
                  attr2 varchar2(100) path 'attr2',
                  attr3 varchar2(100) path 'attr3'
              ) xt
     )
unpivot ( value 
          for softattribute in (attr1 as 'attr1', attr2 as 'attr2', attr3 as 'attr3')
        )
;

ID  SOFTATTRIBUTE  VALUE
--  -------------  -----
 1  attr1          ABC
 1  attr2          XYZ
 1  attr3          PQR

If the set of attributes is only known by inspecting the data, then UNPIVOT won't work - and XMLTABLE won't work either, since the PATH must be a string literal, known to you when you write the code (or known to your dynamic query writing process), it can't be learnt at runtime.

If this is an issue, you may want to reconsider the XML structure; 'attr1' etc. should be values, not labels, just like the values are. (If you are going to work in an EAV model, go all the way in that direction.)

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