Первый вариант (с использованием xmlquery с фильтром xpath) :
with test_table(xmldata) as (
select
q'[
<root>
<itemTypes>
<itemTypesList>
<itemType>400SVFD2</itemType>
<ora:itemType xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="itemTypeMaint" searchZone="C1-ITEMTYPQ" tblKeyField="ITEM_TYPE_CD">First String to Get</ora:itemType>
<errorIfNoValue>C1NO</errorIfNoValue>
<valueType>U</valueType>
<valueSource>C1BF</valueSource>
<value/>
<billFactor>400SVFD2</billFactor>
<ora:billFactor xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="billFactorMaint" searchZone="C1-BFQ" tblKeyField="BF_CD">Second String to Get</ora:billFactor>
<valueAlgorithm/>
</itemTypesList>
</itemTypes>
</root>
]'
from dual
)
select
xmlcast(
xmlquery(
'/root/itemTypes/itemTypesList/*:itemType[namespace-uri()="http://www.oracle.com/something/somethingelse"]/text()'
passing xmltype(xmldata)
returning content
)
as varchar2(100)
) res1
,xmlcast(
xmlquery(
'/root/itemTypes/itemTypesList/*:billFactor[namespace-uri()="http://www.oracle.com/something/somethingelse"]/text()'
passing xmltype(xmldata)
returning content
)
as varchar2(100)
) res2
from test_table
/
Результат:
RES1 RES2
------------------------------ ------------------------------
First String to Get Second String to Get
NB Ваш элемент находится в xmlnamespace 'ora', поэтому вам нужно указать его, но поскольку xmlquery не имеет параметра XMLNAMESPACES, у вас есть 2 варианта их указания:
- добавить объявление xmlnamespace в начале вашего xquery:
'declare namespace ora = "http://www.oracle.com/something/somethingelse";...
или фильтрующие элементы с использованием функции
namespace-uri()
:
*:itemType[namespace-uri()="http://www.oracle.com/something/somethingelse"]
*:element
означает, что вам нужно element
из любых пространств имен xml. [namespace-uri()="..."]
фильтрует элементы по их пространствам имен.
Второй вариант: usint xmltable (xmlnamespaces (...) ...)
with test_table(xmldata) as (
select
q'[
<root>
<itemTypes>
<itemTypesList>
<itemType>400SVFD2</itemType>
<ora:itemType xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="itemTypeMaint" searchZone="C1-ITEMTYPQ" tblKeyField="ITEM_TYPE_CD">First String to Get</ora:itemType>
<errorIfNoValue>C1NO</errorIfNoValue>
<valueType>U</valueType>
<valueSource>C1BF</valueSource>
<value/>
<billFactor>400SVFD2</billFactor>
<ora:billFactor xmlns:ora="http://www.oracle.com/something/somethingelse" navOpt="billFactorMaint" searchZone="C1-BFQ" tblKeyField="BF_CD">Second String to Get</ora:billFactor>
<valueAlgorithm/>
</itemTypesList>
</itemTypes>
</root>
]'
from dual
)
select
xx.*
from test_table
,xmltable(
xmlnamespaces('http://www.oracle.com/something/somethingelse' as "ORA", default ''),
'/root/itemTypes/itemTypesList'
passing xmltype(xmldata)
columns
res1 varchar2(100) path 'ORA:itemType/text()'
,res2 varchar2(100) path 'ORA:billFactor/text()'
) xx
;
Результаты:
RES1 RES2
------------------------------ ------------------------------
First String to Get Second String to Get
1 row selected.
И еще несколько более коротких вариантов, основанных на пространствах имен и фильтрах с подстановочными знаками:
select
xmlcast(
xmlquery(
'/root/itemTypes/itemTypesList/*:itemType[namespace-uri()!=""]/text()'
passing xmltype(xmldata)
returning content
)
as varchar2(100)
) res1
,xmlcast(
xmlquery(
'/root/itemTypes/itemTypesList/*:billFactor[2]/text()'
passing xmltype(xmldata)
returning content
)
as varchar2(100)
) res2
from test_table
Первый возвращает элемент с непустым пространством имен-uri, а второй - просто возвращает второй billFactor без фильтрации по пространствам имен