2016-05-21 68 views
1

我有一個XML文檔,如下所示。我正在嘗試爲所有元素和屬性獲取鍵/值對。我有的查詢獲取所有元素名稱和元素值。但是,我想獲取屬性名稱和屬性值(最好在同一個查詢中,否則在不同的查詢中)。如何將元素和值的搜索擴展到屬性?

XML文檔:

 <bookstore> 
     <book category="COOKING"> 
      <title lang="en">Cook Book</title> 
      <author>Chef Author</author> 
      <year>2015</year> 
      <price>310.00</price> 
     </book> 
     <book category="CHILDREN"> 
      <title lang="en">Kid Story Book</title> 
      <author>KJ Banter</author> 
      <year>2010</year> 
      <price>229.99</price> 
     </book> 
     </bookstore> 

SQL查詢在Oracle中:

WITH tab AS 
    (SELECT xmltype(' 
       <bookstore> 
     <book category="COOKING"> 
      <title lang="en">Cook Book</title> 
      <author>Chef Author</author> 
      <year>2015</year> 
      <price>310.00</price> 
     </book> 
     <book category="CHILDREN"> 
      <title lang="en">Kid Story Book</title> 
      <author>KJ Banter</author> 
      <year>2010</year> 
      <price>229.99</price> 
     </book> 
     </bookstore> 
    ') col 
    FROM dual 
    ) 
    SELECT nodepath,nodevalue 
     FROM tab t, 
     xmltable(' 
     for $i in $tmp/descendant::* 
     where $i/text() != "" 
     return <R><P>{string-join($i/ancestor-or-self::*/name(), "/")}</P><V>{$i/text()}</V></R>' 
     passing t.col AS "tmp" columns 
     nodepath varchar2(1000) path '//P', 
     nodevalue varchar2(1000) path '//V') 

回答

1

鑑於你希望他們在文檔順序,下降爲每一個檢索到的元素,並按照其自身和屬性軸。您需要檢索元素和不同的屬性值,所以應用typeswitch

for $node in /descendant::*/(., @*) 
let $value := (
    typeswitch ($node) 
    case element() return $node/text() 
    case attribute() return data($node) 
    default return() 
) 
where $value 
return <R> 
    <P>{ 
    string-join(($node/name(), $node/ancestor::*/name()), "/") 
    }</P> 
    <V>{ $value }</V> 
</R> 

同時遵守我改變了ancestor-or-self一步一個ancestor步驟,並且明確地返回$node的名字,所以我們沒有區分元素和屬性再次在ancestor軸上。

+0

非常感謝您的快速回復@Jens Erat。當我實現你的解決方案時,我得到一個錯誤「fn:data()的無效參數」。我是xQuery的新手。我相信我可能不得不使用「返回數據($ node/@ *)」而不是「$ node/data()」。我無法弄清楚語法。我非常感謝你對此的幫助。 – Kumar99

+0

對不起,我混入了一些XQuery 3.0符號/語法糖。只需將'$ node/data()'與'data($ node)'交換即可。我相應地更新了我的答案。 –

+0

爲什麼'$ node/data()'不起作用,但是'$ node/text()'和'$ node/name()'做了一些背景:'[fn:] data()'是一個函數,while 'text()'和'name()'是節點測試。 XQuery 3.0中添加了作爲路徑步驟的函數。 –