繁体   English   中英

Oracle-XMLTABLE PATH获取节点祖先

[英]Oracle - XMLTABLE PATH get node ancestor

我有看起来像的XML:

<root>
    <uid>789</uid>
    <element>
      <uid>123</uid>
         <sub>
             <text>XYZ</text>
         </sub>
     </element>
</root>

唯一不变的是<text>节点,而<uid>节点可能为2级。 其余节点可以使用任何名称,因此我不能使用完全限定的路径。

基于<text>节点,我需要找到<uid>节点,该节点在树中最接近或为简单起见2级。

我试过了:

WITH cte("XML") AS (
  SELECT '<root>
             <uid>789</uid>
           <element>
            <uid>123</uid>
            <sub>
                <text>XYZ</text>
            </sub>
            </element>
         </root>'
  FROM dual
)
SELECT x.*, c.*
FROM cte c,XMLTable('//text'
          PASSING XMLTYPE(c."XML")
          COLUMNS
           text VARCHAR2(4000) PATH '.'
            --,guid VARCHAR2(40) PATH '../../uid'  -- unsupported XQuery expression
            --,guid VARCHAR2(40) PATH 'ancestor::node()[2]/uid'  
             -- unsupported XQuery expression\
                 ) x  
WHERE text IS NOT NULL;

db <> fiddle演示

我正在寻找类似于SQL Server的解决方案:

WITH cte("XML") AS (
  SELECT CAST('<root>
             <uid>789</uid>
           <element>
            <uid>123</uid>
            <sub>
                <text>XYZ</text>
            </sub>
            </element>
         </root>' AS XML)
)
SELECT x.value('../../uid[1]', 'VARCHAR(10)') AS uid
     ,s.x.value('.', 'VARCHAR(10)') AS "text"
FROM cte c
CROSS APPLY c."XML".nodes('//text') s(x)

db <> fiddle演示

一种可行的解决方案如下:

SELECT x.*, c.*
FROM cte c,XMLTable('//text/../..'
               PASSING XMLTYPE(c."XML")
               COLUMNS
                 text VARCHAR2(4000) PATH 'uid',
                 guid VARCHAR2(40) PATH 'sub/text'
               ) x  
WHERE text IS NOT NULL;

其结果由两个列123XYZ

您应该使用preceding -它会返回除任何祖先之外的所有节点。
先前收集的顺序是从头到尾。 如果执行preceding::uid或更通用的preceding::*结果将是(789,123)。

将所有内容组合在一起:

WITH cte("XML") AS (
  SELECT '<root>
             <uid>789</uid>
           <element>
            <uid>123</uid>
            <sub>
                <text>XYZ</text>
            </sub>
            </element>
         </root>'
  FROM dual
)
SELECT x.*, c.*
FROM cte c,XMLTable('//text'
          PASSING XMLTYPE(c."XML")
          COLUMNS
           text VARCHAR2(4000) PATH '.'
           ,guid VARCHAR2(40) PATH '(preceding::uid)[last() -1]/data(.)'  -- 2 -levelup            
                 ) x  
WHERE text IS NOT NULL;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM