XML парсинг в Oracle

Выполняю запрос:

with demo as(
select XMLType('<items>
                  <item id="1745212" template="Бокс распределительный">
                    <p60226>DKC</p60226>
                    <p60227>R5PKEB2V81713B4P</p60227>
                    <p69317>Бокс распределительный</p69317>
                  </item>
                  <item id="1745213" template="Бокс распределительный">
                    <p60226>DKC</p60226>
                    <p60227>R5PKEB2V817144P</p60227>
                    <p69317>Бокс распределительный малый</p69317>
                    </item>
                  </items>'
                    ) xml from dual)
select 
         extractvalue(value(dt1),'/item/@id') id,
         dt2.column_value.getrootelement() property_name,
         extractValue(value(dt2),'/*') value
from 
     demo s,
     table(XMLSequence(s.xml.extract('/items/item'))) dt1,
     table(XMLSequence(s.xml.extract('/items/item/*'))) dt2

Ожидаю на выходе 6 строк вида: item_id, property_name (имя тэга), value Получаю 12. Т.е. для каждого item_id все 6 value, хотелось бы только 3, к нему относящиеся. И вроде причина понятна, но вот как пофиксить дублирование ? Спасибо !


Ответы (1 шт):

Автор решения: 0xdb

Таблицы dt1 и dt2 выбирают из одного и того же документа s.xml, и как следствие, декартово произведение этих двух таблиц.

Функции: XMLSequence, extractvalue, getrootelement в 11.2.0.1 объявлены устаревшими, они не рекомендуются больше к применению.

Попробуйте с XMLTable (на db<>fiddle):

with doc (xml) as (
    select xmlType (
        '<items>
          <item id="1745212" template="Бокс распределительный">
            <p60226>DKC</p60226>
            <p60227>R5PKEB2V81713B4P</p60227>
            <p69317>Бокс распределительный</p69317>
          </item>
          <item id="1745213" template="Бокс распределительный">
            <p60226>DKC</p60226>
            <p60227>R5PKEB2V817144P</p60227>
            <p69317>Бокс распределительный малый</p69317>
            </item>
          </items>') from dual)
select id, name, value 
from doc, xmlTable ('/items/item/*' passing doc.xml columns
    id  number path './../@id',
    name varchar2 (8) path 'name()',
    value varchar2 (64) path 'text()')

Результат как и ожидался:

        ID NAME     VALUE                           
---------- -------- --------------------------------
   1745212 p60226   DKC                             
   1745212 p60227   R5PKEB2V81713B4P                
   1745212 p69317   Бокс распределительный          
   1745213 p60226   DKC                             
   1745213 p60227   R5PKEB2V817144P                 
   1745213 p69317   Бокс распределительный малый    

6 rows selected. 
→ Ссылка