1

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は「無効なトークン」エラーメッセージでそれらをすべて拒否します。

私のオラクルのバージョンは「11.2.0.3.0」です。

4

1 に答える 1

2

Extract を使用すると、パスの上位を調べることができますが (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()非推奨です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              

もっと複雑なものが必要な場合は、この回答に示されているように、ノード レベルから必要なものをすべて引き出すことができます。しかし、あなたが言ったことからすると、それはやり過ぎです。

于 2015-11-06T17:18:50.103 に答える