Home > database >  How Extract from XMLTYPE column, corresponding label for value in a tag within a value/label list fr
How Extract from XMLTYPE column, corresponding label for value in a tag within a value/label list fr

Time:11-17

I got a sql from an Oracle table with a XMLTYPE column. The Xml has a tag with a value '2' and in the same xml there is the list with value/label pairs like this:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <characteristics>
        <motor>
            <fuel>2</fuel>
        </motor>
    </characteristics>
    <ValuesList>
        <CarValues>
            <CarValue>
                <value>1</value>
                <label>Diesel</label>
            </CarValue>
            <CarValue>
                <value>2</value>
                <label>Unleaded petrol</label>
            </CarValue>
        </CarValues>
    </ValuesList>
</Root>

With extract() or extractValue() functions it's easy to get the value for tag with any of these staments a, b

SELECT extract(t.xmlColumn, '//fuel/text()').getStringVal() a,
       extractValue(t.xmlColumn, '//fuel') b
  FROM Table t

The problem is I want to get the label text for value '2' from Valueslist 'Unleaded petrol'

I try to get that value with a XPATH expresion like this:

extractValue(t.xmlColumn, '//CarValue/label[../value=//fuel]')

The XPATH has been evaluated with Notepad XML Tools and it works, but there's no way to get any result. it's always null.

Any idea how to achive this? I don't know how to use XMLTABLE or any other solution to this case.

CodePudding user response:

You need to include the /text() part in your attempt:

SELECT
extract(t.xmlColumn,'//fuel/text()').getStringVal() a
,extractValue(t.xmlColumn,'//fuel') b
,extractValue(t.xmlColumn, '//CarValue/label[../value=//fuel/text()]') c
FROM your_table t
A B C
2 2 Unleaded petrol

In your version you're trying to match a label with a value of the node <fuel>2</fuel>, not the text within than node, 2.

Both extract() and extractValue() are deprecated, so you could use XMLQuery instead:

SELECT
XMLQuery('//fuel/text()' passing xmlColumn returning content) a
,XMLQuery('//CarValue/label[../value=//fuel/text()]/text()' passing xmlColumn returning content) a
FROM your_table t
A A
2 Unleaded petrol

Or with XMLTable();

SELECT x.a, x.b
FROM your_table t
CROSS APPLY XMLTable(
  '/'
  passing t.xmlColumn
  columns a number path '//fuel',
    b varchar2(30) path '//CarValue/label[../value=//fuel/text()]'
) x
A B
2 Unleaded petrol

fiddle


If your version of Oracle isn't working with the node traversal using ../ then you could do it the hard way by getting the fuel value and all the id/label pairs with separate XMLTable calls, and then filtering those that match:

SELECT x1.fuel, x2.label
FROM your_table t
CROSS JOIN XMLTable(
  '//fuel'
  passing t.xmlColumn
  columns fuel number path '.'
) x1
JOIN XMLTable(
  '//CarValue'
  passing t.xmlColumn
  columns value number path 'value',
    label varchar2(30) path 'label'
) x2 ON x2.value = x1.fuel
FUEL LABEL
2 Unleaded petrol

fiddle

  • Related