2012-11-13 166 views
-1

Oracle數據庫10g企業版發行10.2.0.5 - 64biXPATH祖先或自身

我試圖從元件輸出hierarhy,我發現,使用祖先或自身根,但不工作的時候:剛剛打印的所有元素(

嗯,我有什麼:

1)像這樣的XML文件。

<Root> 
    <Element1 id="UniqueId1"> 
    <SubElement1 id="UniqueId2"/> 
    <SubElement2 id="UniqueId3"> 
     <LeafElement1 id="UniqueId4"/> 
     <LeafElement1 id="UniqueId5"/> 
    </SubElement2> 
    </Element1> 
    <Element2 id="UniqueId6" AttributeToCheck="true"> 
    <SubElement1 id="UniqueId7"> 
     <LeafElement1 id="UniqueId8"/> 
     <LeafElement1 id="UniqueId9"/> 
    </SubElement1> 
    </Element2> 
</Root> 

2)我的XPath字符串:

//*[@id and contains(@id, "UniqueId8")]/ancestor-or-self::* 

3)我要得到這樣的結果(從找到的元素根):

<Root> 
    <Element2 id="UniqueId6" AttributeToCheck="true"> 
    <SubElement1 id="UniqueId7"> 
     <LeafElement1 id="UniqueId8"/> 
    </SubElement1> 
    </Element2> 
</Root> 

順便說一句,//[@id和包含(@id,「UniqueId8」)]/ancestor-or-self ::/@ id正常。

有誰知道如何解決這個問題,或者只是使用其他操作而不是祖先或自己?

UPDATE:

我只是執行此:

DECLARE 
    v_xml XMLTYPE; 
BEGIN 
    SELECT xmltype('<Root> 
       <Element1 id="UniqueId1"> 
      <SubElement1 id="UniqueId2"/>           <SubElement2 id="UniqueId3"> 
              <LeafElement1 id="UniqueId4"/> 
              <LeafElement1 id="UniqueId5"/> 
             </SubElement2> 
            </Element1> 
            <Element2 id="UniqueId6" AttributeToCheck="true"> 
             <SubElement1 id="UniqueId7"> 
              <LeafElement1 id="UniqueId8"/> 
              <LeafElement1 id="UniqueId9"/> 
             </SubElement1> 
            </Element2> 
           </Root>') 
    into v_xml 
    from dual; 

    select extract(v_xml, '//*[@id="UniqueId9"]/ancestor-or-self::*') 
    into v_xml 
    from dual; 

    dbms_output.put_line(v_xml.getStringVal()); 

END; 

但作爲一個結果,我得到了一些奇怪的事情:

<Root> 
    <Element1 id="UniqueId1"> 
       <SubElement1 id="UniqueId2"/> 
      <SubElement2 id="UniqueId3"> 
            <LeafElement1 id="UniqueId4"/> 
               <LeafElement1 id="UniqueId5"/> 
    </SubElement2> 
    </Element1> 
    <Element2 id="UniqueId6" AttributeToCheck="true"> 
    <SubElement1 id="UniqueId7"> 
    <LeafElement1 id="UniqueId8"/> 
    <LeafElement1 id="UniqueId9"/> 
    </SubElement1></Element2> 
</Root> 
<Element2 id="UniqueId6" AttributeToCheck="true"> 
    <SubElement1 id="UniqueId7"> 
     <LeafElement1 id="UniqueId8"/> 
     <LeafElement1 id="UniqueId9"/> 
    </SubElement1> 
</Element2> 

<SubElement1 id="UniqueId7"> 
    <LeafElement1 id="UniqueId8"/> 
    <LeafElement1 id="UniqueId9"/> 
</SubElement1> 

<LeafElement1 id="UniqueId9"/> 

回答

0

傢伙尼克xtender找到XPATH偉大的解決方案,它確實有效:

with t_xml as (select xmltype(' 
    <Root> 
     <Element1 id="UniqueId1"> 
     <SubElement1 id="UniqueId2"/> 
     <SubElement2 id="UniqueId3"> 
      <LeafElement1 id="UniqueId4"/> 
      <LeafElement1 id="UniqueId5"/> 
     </SubElement2> 
     </Element1> 
     <Element2 id="UniqueId6" AttributeToCheck="true"> 
     <SubElement1 id="UniqueId7"> 
      <LeafElement1 id2="UniqueId8"/> 
      <LeafElement1 id="UniqueId9"/> 
     </SubElement1> 
     </Element2> 
    </Root>') x from dual) 
    select 
     t_xml.* 
     ,updatexml(x,'//*[not (descendant-or-self::*[@id2="UniqueId8"])]',chr(10)) upd 
    from t_xml 
2

的XPath只允許您選擇輸入文檔中的節點,它不允許您更改文檔的結構或創建一個新的節點正在更改(添加,刪除,操縱)。因此,一旦你用你的路徑表達式選擇了根元素並輸出結果,你當然會輸出它所包含的根元素和所有節點。

因此,XPath無法完成您想要完成的工作,因爲您需要使用XQuery或XSLT;這樣,您將能夠創建一個新的文檔,其中包含您不想刪除的節點。 Fragment input xhtml to seperate xhtml files with ancestor nodes deails是一個示例,其中XSLT用於過濾不是祖先或某個節點的子項的根元素的後代節點。它比你需要的要多,因爲它爲幾個節點做了這些,並創建了幾個結果文檔,但部分代碼正在做你想做的。不過,我不知道您是否可以在XSLT 2.0中使用XSLT或XSLT 2.0,所以我不會嘗試將這些代碼適用於您的輸入示例,除非您明確指出可以使用XSLT以及您可以使用哪種版本的XSLT在Oracle的上下文中使用。

+0

我不想改變結構,我只是需要獲得像這樣的結果http://chris.photobooks.com/xml/default.htm?state=9D – user485553

+0

那麼即使該頁面顯示了完整的樹,只有它突出顯示了某些節點。也許DazzaL的回答比我引用XQuery或XSLT更有幫助,但我不熟悉Oracle中的XML數據類型支持。 –

+0

我想你也會對XQuery感興趣。我有XQuery解決方案https://forums.oracle.com/forums/thread.jspa?threadID=2463473&tstart=0但是我仍然在尋找XPath解決方案! – user485553

1

正如Martin所說,您不能使用XPath構造輸入中不存在的樹。

還有一點:請注意XPath表達式選擇節點。可以認爲它是將一組指針返回到輸入文檔中的節點。運行XPath查詢的客戶端環境通過顯示以該節點爲根的子樹來顯示這些節點是很常見的。但是XPath表達式並沒有選擇整個樹,它只是選擇了根,並且節點下面的子樹的顯示可能會讓你感到困惑。

1

試試這個XSL方法:

SQL> with xml as (select xmltype('<Root> 
    2 <Element1 id="UniqueId1"> 
    3  <SubElement1 id="UniqueId2"/> 
    4  <SubElement2 id="UniqueId3"> 
    5  <LeafElement1 id="UniqueId4"/> 
    6  <LeafElement1 id="UniqueId5"/> 
    7  </SubElement2> 
    8 </Element1> 
    9 <Element2 id="UniqueId6" AttributeToCheck="true"> 
10  <SubElement1 id="UniqueId7"> 
11  <LeafElement1 id="UniqueId8"/> 
12  <LeafElement1 id="UniqueId9"/> 
13  </SubElement1> 
14 </Element2> 
15 </Root>') xml from dual), 
16 xsl as (select xmltype(' 
17 <xsl:stylesheet version="1.0" 
18 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
19 <xsl:template match="node()|@*"> 
20 <xsl:copy> 
21  <xsl:apply-templates select="*[descendant-or-self::*[contains(@id,''UniqueId8'')]]|@*"/> 
22 </xsl:copy> 
23 </xsl:template> 
24 </xsl:stylesheet>') xsl from dual) 
25 select xm.xml.transform(xs.xsl) 
26 from xml xm, xsl xs; 

XM.XML.TRANSFORM(XS.XSL) 
-------------------------------------------------------------------------------- 

<Root> 
<Element2 id="UniqueId6" AttributeToCheck="true"> 
    <SubElement1 id="UniqueId7"> 
    <LeafElement1 id="UniqueId8"> 
    </LeafElement1> 
    </SubElement1> 
</Element2> 
</Root> 
+0

此功能的一個平臺可以在這裏玩:http://sqlfiddle.com/#!4/d41d8/4324 – DazzaL

+0

是多餘的,但它比我的查詢更接近。 – user485553

+0

啊對不起啊。 XSL可以解決它然後修改。 – DazzaL