如何获取 Oracle XPath 表达式中父元素的名称?

How to get the name of the parent element in an Oracle XPath expression?

我有一个查询可以从我的 clob 中提取一些 XML 节点。

select pid, name, xml from (
select d.pid, d.name
, EXTRACT(xmltype(d.data), '//ns1:myId', 'xmlns:ns1="http://acme.com/') xml
from DATA d
order by d.pid desc
)
;

但我想看看提取的 xmlnode 的父元素名称到底是什么。我试过了

, EXTRACT(xmltype(d.data), '//ns1:myId/../name()', ...) xml

, EXTRACT(xmltype(d.data), '//ns1:myId/name()', ...) xml

, EXTRACT(xmltype(d.data), '//ns1:myId/local-name()', ...) xml

但 Oracle 拒绝了所有这些并显示 "invalid token" 错误消息。

我的 Oracle 版本是“11.2.0.3.0”。

Extract 可让您查看更高的路径,但是(如 MOS 文档 301709.1 中所述;它适用于 9i 但似乎仍然有效,除了显示的错误之外):

Using the XPATH function name() to return the element name is not possible, because the methods extract() and extractValue() currently only support XPATH operations returning a node-set.

所以不能在当前节点或父节点上使用name()local-name()等函数。该文档中有一种解决方法,可以从他们的示例中稍微简化为:

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()

两者的演示:

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>                      

但是extract() is deprecated anyway. You could do this with 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              

如果你需要更复杂的东西,你可以从节点级别中提取任何你需要的东西,as shown in this answer;但从你所说的来看,这里有点过分了。