Oi, Claudio.
O XML de exemplo me parece estar errado.
De qualquer forma seguem algumas dicas com extração de XML. Espero que sejam úteis.
1- Você não precisa saber a quantidade elementos repetidos para iterar entre eles. Usando a sintaxe do XMLTABLE é possível fazer um SELECT no XML de forma bastante simples como se ele fosse uma tabela
Selecionar tudo
SELECT *
FROM Xmltable('det/prod' PASSING XMLTYPE('<det nItem = "4">
<prod>
<cprod>produto 1</cprod>
</prod>
<prod>
<cprod>produto 2</cprod>
</prod>
<prod>
<cprod>produto 3</cprod>
</prod>
<prod>
<cprod>produto 4</cprod>
</prod>
</det>') COLUMNS cprod VARCHAR2(4000) PATH 'cprod')
;
2- Se realmente precisa ler um atributo de uma tag, a sua consulta pode ficar assim:
Selecionar tudo
SELECT nitem
FROM xmltable('det' passing xmltype('
<det nItem = "4">
<prod>
<cprod>produto 1</cprod>
</prod>
<prod>
<cprod>produto 2</cprod>
</prod>
<prod>
<cprod>produto 3</cprod>
</prod>
<prod>
<cprod>produto 4</cprod>
</prod>
</det>') columns nItem VARCHAR2(4000) path '@nItem');
.
3- Se o XML possuir tags com valores em diferentes níveis (pai e filho) você deve utilizar uma XMLTABLE para cada nível.
Para realizar a junção entre elas use o próprio XML extraído do nível mais alto:
Selecionar tudo
SELECT nitem, cprod
FROM xmltable('det' passing xmltype('
<det nItem = "4">
<prod>
<cprod>produto 1</cprod>
</prod>
<prod>
<cprod>produto 2</cprod>
</prod>
<prod>
<cprod>produto 3</cprod>
</prod>
<prod>
<cprod>produto 4</cprod>
</prod>
</det>') columns nItem VARCHAR2(4000) path '@nItem'
,produtos XMLTYPE path '/') det,
Xmltable('det/prod' PASSING det.produtos COLUMNS cprod VARCHAR2(4000) PATH 'cprod')
Espero que ajude!