Find parent node name for all the multiple child nodes using XMLTABLE in Oracle

73 Views Asked by At

We have a table named XML_TEST which contains XML as XMLTYPE. XML sample and its structure is as below,

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<invoice>
    <AR_ITEMS elem="2">
        <SERVICE_OBJ>0.0.0.1 /service/telco/gsm/telephony 44745735656 0</SERVICE_OBJ>
        <ITEM_NO>B1-730869289,5</ITEM_NO>
        <NAME>Cycle forward</NAME>
        <ITEM_TOTAL>637.5</ITEM_TOTAL>
        <DUE_T>1676408400</DUE_T>
        <DUE>637.5</DUE>
        <DISPUTED>0</DISPUTED>
        <EVENT_POID_LIST></EVENT_POID_LIST>
        <ACCOUNT_OBJ>0.0.0.1 /account 44709279566 22</ACCOUNT_OBJ>
        <BILLINFO_OBJ>0.0.0.1 /billinfo 44709278926 0</BILLINFO_OBJ>
        <AR_BILLINFO_OBJ>0.0.0.1 /billinfo 44709278926 0</AR_BILLINFO_OBJ>
        <BILL_OBJ>0.0.0.1 /bill 48486806027 0</BILL_OBJ>
        <EFFECTIVE_T>1673730000</EFFECTIVE_T>
        <CREATED_T>1673732390</CREATED_T>
        <ITEM_OBJ>0.0.0.1 /item/cycle_forward 340795877581277892 1</ITEM_OBJ>
        <DEVICE_ID>97455066626</DEVICE_ID>
        <PRIMARY_MSID></PRIMARY_MSID>
        <AAC_ACCESS></AAC_ACCESS>
        <EVENTS elem="110">
            <END_T>1673730000</END_T>
            <START_T>1673730000</START_T>
            <CREATED_T>1673732391</CREATED_T>
            <NET_QUANTITY>1</NET_QUANTITY>
            <SYS_DESCR>Cycle Forward Fees (srvc): Business Unlimited VIP</SYS_DESCR>
            <RERATE_OBJ>0.0.0.0  0 0</RERATE_OBJ>
            <SESSION_OBJ>0.0.0.1 /event/session 0 0</SESSION_OBJ>
            <TIMEZONE_ADJ_END_T>1673732391</TIMEZONE_ADJ_END_T>
            <RATED_TIMEZONE_ID>Asia/Qatar</RATED_TIMEZONE_ID>
            <ITEM_OBJ>0.0.0.1 /item/cycle_forward 340795877581277892 0</ITEM_OBJ>
            <EVENT_OBJ>0.0.0.1 /event/billing/product/fee/cycle/cycle_forward_monthly 340795877581278916 0</EVENT_OBJ>
            <IMPACT_CATEGORY>Rate 1</IMPACT_CATEGORY>
            <ACCOUNT_OBJ>0.0.0.1 /account 44709279566 0</ACCOUNT_OBJ>
        </EVENTS>
        <EVENTS elem="111">
            <END_T>1673730000</END_T>
            <START_T>1673730000</START_T>
            <CREATED_T>1673732391</CREATED_T>
            <NET_QUANTITY>1</NET_QUANTITY>
            <SYS_DESCR>Cycle Forward Fees (srvc): Business Unlimited VIP</SYS_DESCR>
            <RERATE_OBJ>0.0.0.0  0 0</RERATE_OBJ>
            <SESSION_OBJ>0.0.0.1 /event/session 0 0</SESSION_OBJ>
            <TIMEZONE_ADJ_END_T>1673732391</TIMEZONE_ADJ_END_T>
            <RATED_TIMEZONE_ID>Asia/Qatar</RATED_TIMEZONE_ID>
            <ITEM_OBJ>0.0.0.1 /item/cycle_forward 340795877581277892 0</ITEM_OBJ>
            <EVENT_OBJ>0.0.0.1 /event/billing/product/fee/cycle/cycle_forward_monthly 340795877581278916 0</EVENT_OBJ>
            <IMPACT_CATEGORY>Rate 1</IMPACT_CATEGORY>
            <ACCOUNT_OBJ>0.0.0.1 /account 44709279566 0</ACCOUNT_OBJ>
        </EVENTS>
    </AR_ITEMS>
</invoice>

I have written one query as below,

select AR_ITEMS_EVENTS.* from XWDDSB.XML_TEST,
        XMLTABLE(
        '/invoice/*[self::SUB_ITEMS or self::AR_ITEMS or self::OTHER_ITEMS]/EVENTS' 
        PASSING XML_DATA 
        COLUMNS
        ITEMTYPE varchar2(30) path 'name()',
        "EVENT_OBJ" NVARCHAR2(255) PATH 'EVENT_OBJ',
        "IMPACT_CATEGORY" NVARCHAR2(255) PATH 'IMPACT_CATEGORY'
        
        )AR_ITEMS_EVENTS;

The above query returns ITEMTYPE as EVENTS as in the below image. But I do need ITEMTYPE as EVENTS node's parent node name. So the above query should return ITEMTYPE as AR_ITEMS.

enter image description here

Can anyone help me write a query using XMLTABLE so that I get ITEMTYPE as parent node name for all the child nodes in the result set.

Please note that there will be multiple EVENTS nodes inside the parent AR_ITEMS node. And we dont want to change XMLTYPE data type to something else like CLOB to achieve this.

We are using Oracle 19c

1

There are 1 best solutions below

1
Connor McDonald On

Maybe start as the AR_EVENT level to get your ITEMTYPE, and then drill-down into the EVENTS to pick up the rest, eg

SQL> with t as ( select
  2  xmltype('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  3  <invoice>
  4      <AR_ITEMS elem="2">
  5          <SERVICE_OBJ>0.0.0.1 /service/telco/gsm/telephony 44745735656 0</SERVICE_OBJ>
  6          <ITEM_NO>B1-730869289,5</ITEM_NO>
  7          <NAME>Cycle forward</NAME>
  8          <ITEM_TOTAL>637.5</ITEM_TOTAL>
  9          <DUE_T>1676408400</DUE_T>
 10          <DUE>637.5</DUE>
 11          <DISPUTED>0</DISPUTED>
 12          <EVENT_POID_LIST></EVENT_POID_LIST>
 13          <ACCOUNT_OBJ>0.0.0.1 /account 44709279566 22</ACCOUNT_OBJ>
 14          <BILLINFO_OBJ>0.0.0.1 /billinfo 44709278926 0</BILLINFO_OBJ>
 15          <AR_BILLINFO_OBJ>0.0.0.1 /billinfo 44709278926 0</AR_BILLINFO_OBJ>
 16          <BILL_OBJ>0.0.0.1 /bill 48486806027 0</BILL_OBJ>
 17          <EFFECTIVE_T>1673730000</EFFECTIVE_T>
 18          <CREATED_T>1673732390</CREATED_T>
 19          <ITEM_OBJ>0.0.0.1 /item/cycle_forward 340795877581277892 1</ITEM_OBJ>
 20          <DEVICE_ID>97455066626</DEVICE_ID>
 21          <PRIMARY_MSID></PRIMARY_MSID>
 22          <AAC_ACCESS></AAC_ACCESS>
 23          <EVENTS elem="110">
 24              <END_T>1673730000</END_T>
 25              <START_T>1673730000</START_T>
 26              <CREATED_T>1673732391</CREATED_T>
 27              <NET_QUANTITY>1</NET_QUANTITY>
 28              <SYS_DESCR>Cycle Forward Fees (srvc): Business Unlimited VIP</SYS_DESCR>
 29              <RERATE_OBJ>0.0.0.0  0 0</RERATE_OBJ>
 30              <SESSION_OBJ>0.0.0.1 /event/session 0 0</SESSION_OBJ>
 31              <TIMEZONE_ADJ_END_T>1673732391</TIMEZONE_ADJ_END_T>
 32              <RATED_TIMEZONE_ID>Asia/Qatar</RATED_TIMEZONE_ID>
 33              <ITEM_OBJ>0.0.0.1 /item/cycle_forward 340795877581277892 0</ITEM_OBJ>
 34              <EVENT_OBJ>0.0.0.1 /event/billing/product/fee/cycle/cycle_forward_monthly 340795877581278916 0</EVENT_OBJ>
 35              <IMPACT_CATEGORY>Rate 1</IMPACT_CATEGORY>
 36              <ACCOUNT_OBJ>0.0.0.1 /account 44709279566 0</ACCOUNT_OBJ>
 37          </EVENTS>
 38          <EVENTS elem="111">
 39              <END_T>1673730000</END_T>
 40              <START_T>1673730000</START_T>
 41              <CREATED_T>1673732391</CREATED_T>
 42              <NET_QUANTITY>1</NET_QUANTITY>
 43              <SYS_DESCR>Cycle Forward Fees (srvc): Business Unlimited VIP</SYS_DESCR>
 44              <RERATE_OBJ>0.0.0.0  0 0</RERATE_OBJ>
 45              <SESSION_OBJ>0.0.0.1 /event/session 0 0</SESSION_OBJ>
 46              <TIMEZONE_ADJ_END_T>1673732391</TIMEZONE_ADJ_END_T>
 47              <RATED_TIMEZONE_ID>Asia/Qatar</RATED_TIMEZONE_ID>
 48              <ITEM_OBJ>0.0.0.1 /item/cycle_forward 340795877581277892 0</ITEM_OBJ>
 49              <EVENT_OBJ>0.0.0.1 /event/billing/product/fee/cycle/cycle_forward_monthly 340795877581278916 0</EVENT_OBJ>
 50              <IMPACT_CATEGORY>Rate 1</IMPACT_CATEGORY>
 51              <ACCOUNT_OBJ>0.0.0.1 /account 44709279566 0</ACCOUNT_OBJ>
 52          </EVENTS>
 53      </AR_ITEMS>
 54  </invoice>') x from dual )
 55  select a.itemtype, b.* from t,
 56          XMLTABLE(
 57          '/invoice/*[self::SUB_ITEMS or self::AR_ITEMS or self::OTHER_ITEMS]'
 58          PASSING x
 59          COLUMNS
 60          ITEMTYPE varchar2(30) path 'name()',
 61          EVENTS xmltype PATH 'EVENTS'
 62          ) a,
 63          XMLTABLE('/EVENTS'
 64          passing a.events
 65          columns
 66          "EVENT_OBJ" NVARCHAR2(255) PATH 'EVENT_OBJ',
 67          "IMPACT_CATEGORY" NVARCHAR2(255) PATH 'IMPACT_CATEGORY'
 68          ) b;

ITEMTYPE                       EVENT_OBJ                      IMPACT_CATEGORY
------------------------------ ------------------------------ ------------------------------
AR_ITEMS                       0.0.0.1 /event/billing/product Rate 1
                               /fee/cycle/cycle_forward_month
                               ly 340795877581278916 0

AR_ITEMS                       0.0.0.1 /event/billing/product Rate 1
                               /fee/cycle/cycle_forward_month
                               ly 340795877581278916 0


2 rows selected.

SQL>
SQL>
SQL>