我有一个查询,从我的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拒绝所有带有“无效令牌”错误消息的消息。
我的Oracle版本是“ 11.2.0.3.0”。
最佳答案
提取可让您向上看路径,但是(如MOS文档301709.1所述;它适用于9i,但除了显示的错误外,它仍然有效):
使用XPATH函数name()返回元素名称是不可能的,因为方法extract()和extractValue()当前仅支持返回节点集的XPATH操作。
因此,您不能在当前或父节点上使用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。您可以使用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中提取所需的任何内容。但是根据您的说法,这太过分了。