Search code examples
xmloracle-databaseclob

Extracting value from xml clob with Namespace using Oracle pl/sql


I am currently trying to extract value from the clob column but always getting the result as null.

I tried out many possible scenarios but for me it is always returning as null.

Attached is the actual xml

<TenderOffer xmlns="http://xmlns.oracle.com/apps/otm">
    <Shipment>
        <ShipmentHeader/>
        <SEquipment/>
        <ShipmentStop/>
        <ShipmentStop/>
        <Location/>
        <Location/>
        <Release/>
        <RATE_OFFERING>
            <RATE_OFFERING_ROW>
                <USER_CLASSIFICATION3>ZXF</USER_CLASSIFICATION3>
            </RATE_OFFERING_ROW>
        </RATE_OFFERING>
    </Shipment>
    </TenderOffer>

and below is the actual query,

select 
        itc.element_name,
        extractvalue(XMLTYPE(XML_BLOB), '/TenderOffer/Shipment/RATE_OFFERING/RATE_OFFERING_ROW/USER_CLASSIFICATION3/text()'),
    XMLTYPE(XML_BLOB)
        from i_transaction itc
        where itc.i_transaction_no = 31553115
            and rownum = 1

Solution

  • Your updated XML has a namespace, which finally reveals the issue. You need to specify the namespace as part of the XML extraction, which is simpler with the XMLTable approach; in this case you can just treat it as the default namespace:

    select itc.element_name, x.user_classification3
    from i_transaction itc
    cross join xmltable(
      xmlnamespaces(default 'http://xmlns.oracle.com/apps/otm'),
        '/TenderOffer/Shipment/RATE_OFFERING/RATE_OFFERING_ROW'
      passing xmltype(itc.xml_blob)
      columns user_classification3 varchar2(10) path 'USER_CLASSIFICATION3'
    ) x
    where itc.i_transaction_no = 31553115
    and rownum = 1;
    
    ELEMENT_NA USER_CLASS
    ---------- ----------
    dummy      ZXF       
    

    or with XMLQuery:

    select itc.element_name, xmlquery(
      'declare default element namespace "http://xmlns.oracle.com/apps/otm"; (: :)
        /TenderOffer/Shipment/RATE_OFFERING/RATE_OFFERING_ROW/USER_CLASSIFICATION3/text()'
      passing xmltype(itc.xml_blob)
      returning content
    ) x
    from i_transaction itc
    where itc.i_transaction_no = 31553115
    and rownum = 1;
    
    ELEMENT_NA X                                                                               
    ---------- --------------------------------------------------------------------------------
    dummy      ZXF                                                                             
    

    If you wanted to keep using the deprecated extractvalue() function you can supply the namespace as an argument to that too, again as shown in the documentation:

    select itc.element_name,
      extractvalue(xmltype(xml_blob),
        '/TenderOffer/Shipment/RATE_OFFERING/RATE_OFFERING_ROW/USER_CLASSIFICATION3/text()',
        'xmlns="http://xmlns.oracle.com/apps/otm"')
    from i_transaction itc where itc.i_transaction_no = 31553115 and rownum = 1;