sql >> Base de Datos >  >> RDS >> Oracle

¿Cómo obtener el nombre del elemento principal en una expresión Oracle XPath?

Extraer le permite buscar más arriba en la ruta, pero (como se indica en el documento MOS 301709.1; que es para 9i pero aún parece válido, además del error que se muestra):

Entonces no puedes usar el name() , local-name() etc. funciones, en el nodo actual o principal. Hay una especie de solución en ese documento, que se puede simplificar ligeramente a partir de su ejemplo a:

EXTRACT(xmltype(d.data), '//ns1:myId/..', 
  'xmlns:ns1="http://acme.com/').getRootElement() xml2

O en una forma ligeramente diferente:

xmltype(d.data).extract('//ns1:myId/..', 
  'xmlns:ns1="http://acme.com/').getRootElement()

Demostración con ambos:

with data (pid, name, data) as (
  select 42, 'Test', '<?xml version="1.0" encoding="ISO-8859-1"?>
  <ns1:root xmlns:ns1="http://acme.com/"><ns1:parent><ns1:myId>1234</ns1:myId></ns1:parent></ns1:root>' from dual
)
select d.pid, d.name
, EXTRACT(xmltype(d.data), '//ns1:myId', 'xmlns:ns1="http://acme.com/') xml
, EXTRACT(xmltype(d.data), '//ns1:myId/..', 'xmlns:ns1="http://acme.com/').getRootElement() xml2
, xmltype(d.data).extract('//ns1:myId/..', 'xmlns:ns1="http://acme.com/').getRootElement() xml3
from DATA d
order by d.pid desc
;

       PID NAME XML                            XML2       XML3     
---------- ---- ------------------------------ ---------- ----------
        42 Test <ns1:myId xmlns:ns1="http://ac parent     parent    
                me.com/">1234</ns1:myId>                      

Pero extract() está en desuso de todos modos . Podría hacer esto con XMLTable :

with data (pid, name, data) as (
  select 42, 'Test', '<?xml version="1.0" encoding="ISO-8859-1"?>
  <ns1:root xmlns:ns1="http://acme.com/"><parent><myId>1234</myId></parent></ns1:root>' from dual
)
select d.pid, d.name, x.*
from data d
cross join xmltable(xmlnamespaces('http://acme.com/' as "ns1"),
  '/ns1:*//myId'
  passing xmltype(d.data)
  columns myId number path '.',
    parent varchar2(20) path './../local-name()'
) x
order by d.pid desc;

       PID NAME       MYID PARENT             
---------- ---- ---------- --------------------
        42 Test       1234 parent              

Si necesita algo más complicado, puede extraer lo que necesite de los niveles de nodo, como se muestra en esta respuesta; pero por lo que has dicho, eso es exagerado aquí.