xmloracle-databasexmltype

Use Oracle to parse an XML with multiple sub nodes


I need to parse in Oracle an XML with multiple sub elements but I keep getting multi-item sequence error. I saw that it was discussed before, I tried the cross join approach with two XMLTABLE but it still does not work and I guess I'm stuck. Can you please suggest a solution?

This is the XML:

<dataView>
   <categoryId>22</categoryId>
   <tableReferenceId>2533050</tableReferenceId>
   <noOfColumnsToFixHorizontally>0</noOfColumnsToFixHorizontally>
   <fieldOptions>
      <id>2533805</id>
      <fieldId>2446226</fieldId>
      <entityId>2446223</entityId>
      <fieldHeaderLabel>Product ID</fieldHeaderLabel>
      <displayedByDefault>true</displayedByDefault>
      <filterableAndSortable>true</filterableAndSortable>
      <quickFilterValues>Laptops</quickFilterValues>
      <quickFilterValues>Monitors</quickFilterValues>
      <quickFilterValues>PCs</quickFilterValues>
      <columnWidth>MEDIUM_SMALL</columnWidth>
      <fieldType>DVFO_DATA</fieldType>
   </fieldOptions>
   <fieldOptions>
      <id>2533806</id>
      <fieldId>563</fieldId>
      <fieldHeaderLabel>Quarter</fieldHeaderLabel>
      <displayedByDefault>true</displayedByDefault>
      <filterableAndSortable>true</filterableAndSortable>
      <quickFilterValues>Quarter 3 2016</quickFilterValues>
      <quickFilterValues>Quarter 4 2016</quickFilterValues>
      <quickFilterValues>Quarter 1 2017</quickFilterValues>
      <quickFilterValues>Quarter 2 2017</quickFilterValues>
      <columnWidth>MEDIUM_SMALL</columnWidth>
      <fieldType>DVFO_DATA</fieldType>
   </fieldOptions>
</dataView>

The expected result would be the distinct values from the quickFilterValues node:

Laptops
Monitors
PCs
Quarter 3 2016
Quarter 4 2016
Quarter 1 2017
Quarter 2 2017

This is a query I tried to use:

with plm as (select '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><dataView><categoryId>22</categoryId><tableReferenceId>2533050</tableReferenceId><noOfColumnsToFixHorizontally>0</noOfColumnsToFixHorizontally><fieldOptions><id>2533805</id><fieldId>2446226</fieldId><entityId>2446223</entityId><fieldHeaderLabel>Product ID</fieldHeaderLabel><displayedByDefault>true</displayedByDefault><filterableAndSortable>true</filterableAndSortable><quickFilterValues>Laptops</quickFilterValues><quickFilterValues>Monitors</quickFilterValues><quickFilterValues>PCs</quickFilterValues><columnWidth>MEDIUM_SMALL</columnWidth><fieldType>DVFO_DATA</fieldType></fieldOptions><fieldOptions><id>2533806</id><fieldId>563</fieldId><fieldHeaderLabel>Quarter</fieldHeaderLabel><displayedByDefault>true</displayedByDefault><filterableAndSortable>true</filterableAndSortable><quickFilterValues>Quarter 3 2016</quickFilterValues><quickFilterValues>Quarter 4 2016</quickFilterValues><quickFilterValues>Quarter 1 2017</quickFilterValues><quickFilterValues>Quarter 2 2017</quickFilterValues><columnWidth>MEDIUM_SMALL</columnWidth><fieldType>DVFO_DATA</fieldType></fieldOptions></dataView>
' x from dual)
SELECT *
  FROM plm, 
       XMLTable('/dataView/fieldOptions'
                PASSING xmltype(x)
                COLUMNS
                   fo  VARCHAR2(250) PATH 'quickFilterValues'
               )

But i get the 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" *Cause: The XQuery sequence passed in had more than one item. *Action: Correct the XQuery expression to return a single item sequence.


Solution

  • You can use:

    SELECT x.fo
    FROM   plm p
           CROSS APPLY XMLTable(
             '/dataView/fieldOptions/quickFilterValues'
             PASSING xmltype(p.x)
             COLUMNS
               fo  VARCHAR2(250) PATH '.'
          ) x
    

    Which, for the sample data:

    CREATE TABLE plm (x) AS
    SELECT '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><dataView><categoryId>22</categoryId><tableReferenceId>2533050</tableReferenceId><noOfColumnsToFixHorizontally>0</noOfColumnsToFixHorizontally><fieldOptions><id>2533805</id><fieldId>2446226</fieldId><entityId>2446223</entityId><fieldHeaderLabel>Product ID</fieldHeaderLabel><displayedByDefault>true</displayedByDefault><filterableAndSortable>true</filterableAndSortable><quickFilterValues>Laptops</quickFilterValues><quickFilterValues>Monitors</quickFilterValues><quickFilterValues>PCs</quickFilterValues><columnWidth>MEDIUM_SMALL</columnWidth><fieldType>DVFO_DATA</fieldType></fieldOptions><fieldOptions><id>2533806</id><fieldId>563</fieldId><fieldHeaderLabel>Quarter</fieldHeaderLabel><displayedByDefault>true</displayedByDefault><filterableAndSortable>true</filterableAndSortable><quickFilterValues>Quarter 3 2016</quickFilterValues><quickFilterValues>Quarter 4 2016</quickFilterValues><quickFilterValues>Quarter 1 2017</quickFilterValues><quickFilterValues>Quarter 2 2017</quickFilterValues><columnWidth>MEDIUM_SMALL</columnWidth><fieldType>DVFO_DATA</fieldType></fieldOptions></dataView>' FROM DUAL;
    

    Outputs:

    FO
    Laptops
    Monitors
    PCs
    Quarter 3 2016
    Quarter 4 2016
    Quarter 1 2017
    Quarter 2 2017

    fiddle