2012-12-28 56 views
1

我嘗試使用xQuery處理多個XML文件(迄今爲止的體驗非常有限)。該XML的重要組成部分,可以提出這樣的:通過處理異構XML樹來輸出xQuery

<?xml version="1.0" encoding="UTF-8"?> 
<ZOO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 

<Mammals> 
<marsupials> 
    <zoo> 
     <kangaroo> 
     <number>25</number> 
      <red_kangaroo> 
       <number>1</number> 
      </red_kangaroo> 
     </kangaroo> 
    </zoo> 
</marsupials> 

<ruminants> 
    <giraffe> 
     <number>10</number> 
     <comments>Comment Text.</comments> 
    </giraffe> 
    <antelope> 
     <number>20</number> 
     <comments>Comment Text.</comments> 
    </antelope> 
    <elk> 
     <number>2</number> 
     <comments>Comment Text.</comments> 
    </elk> 
    <mouflon> 
     <number>3</number> 
     <comments>Comment Text.</comments> 
    </mouflon> 
    <ibex> 
     <number>2</number> 
     <comments>Comment Text.</comments> 
    </ibex> 
    <ox> 
     <number>5</number> 
     <comments>Comment Text.</comments> 
    </ox> 
    <other_ruminants> 
     <other_ruminant> 
      <name>bison</name> 
      <number>1</number> 
      <comments>Comment Text.</comments> 
     </other_ruminant> 
     <other_ruminant> 
      <name>musk ox</name> 
      <number>2</number> 
      <comments>Comment Text.</comments> 
     </other_ruminant> 
    </other_ruminants> 
</ruminants> 

<rodents> 
    <rodent> 
     <name>hamster</name> 
     <number>10</number> 
    </rodent> 
    <rodent> 
     <name>squirrel</name> 
     <number>15</number> 
     <comments>Comment Text.</comments> 
    </rodent> 
    <rodent> 
     <other_rodent> 
      <other_rodent_name>porcupine</other_rodent_name> 
      <comment>Comment Text.</comment> 
     </other_rodent> 
     <number>1</number> 
    </rodent> 
    <rodent> 
     <other_rodent> 
      <other_rodent_name>beaver</other_rodent_name> 
      <comment>Comment Text.</comment> 
     </other_rodent> 
     <number>2</number> 
    </rodent> 
</rodents> 
</Mammals> 

</ZOO> 

正如你看到的,有袋動物和最反芻動物都有自己的標記。然而,齧齒動物只有標籤<rodent>,它們在標籤<name>內命名,並且每個文件中都有不同的齧齒動物。

我試圖使文件的審計看起來像這樣(我的工作wirh BaseX 7.5):

for $z in /ZOO, $m in $z/Mammals 
return 
<count> 
<!-- file_id comes here later --> 
<kangaroo>'{$z//kangaroo/number/text()}'</kangaroo> 
<giraffe>'{$z//giraffe/number/text()}'</giraffe> 
</count> 

...但當然齧齒類動物部分,因爲不同的齧齒動物的數量,我不能這樣做他們的名字在不同的文件中是不同的。 期望的輸出將是(對於所示的文件片段):

<count> 
<!-- file_id comes here later --> 
<kangaroo>'25'</kangaroo> 
<giraffe>'10'</giraffe> 
<!-- other animals with own tags come here - antelope, mouflon etc. --> 
<!-- the problems begins here: how to output the rodents in the same way: --> 
<hamster>'10'</hamster> 
<squirrel>'15'</squirrel> 
<!-- the "other rodents" is the next story, but perhaps the solution could be similar? --> 
</count> 

這可能嗎?您的幫助將不勝感激!

更新:換句話說:我怎麼能輸出,沒有自己的標籤項目(齧齒動物不同時,例如最反芻動物做),並在不同的文件數量的不同?

更新2:我繼續嘗試自己在此期間,這裏是什麼,我現在得到:

查詢(只袋鼠,長頸鹿和齧齒動物很有趣):

for $z in /ZOO, $m in $z/Mammals 
return 
<count> 
<!-- file_id comes here later --> 
<kangaroo>{$z//kangaroo/number/text()}</kangaroo> 
<giraffe>{$z//giraffe/number/text()}</giraffe> 
{ for $r in $m//rodent 
    return 
    if ($r//name/text()) then 
    <sp>{$r//name/text()};{$r//number/text()}</sp> 
    else 
    <sp>{$r//other_rodent_name/text()};{$r//number/text()}</sp> 
} 
</count> 

實際輸出:

<count> 
    <!-- file_id comes here later --> 
    <kangaroo>25</kangaroo> 
    <giraffe>10</giraffe> 
    <sp>hamster;10</sp> 
    <sp>squirrel;15</sp> 
    <sp>porcupine;1</sp> 
    <sp>beaver;2</sp> 
</count> 

也就是說,我莫名其妙輸出騎着車nts(倉鼠,松鼠,豪豬和海狸)與相應的數字作爲解決方法,我可能後來編輯輸出... 然而,我希望有齧齒動物後動態命名的標籤,例如。這種方式:

<count> 
    <!-- file_id comes here later --> 
    <kangaroo>25</kangaroo> 
    <giraffe>10</giraffe> 
    <hamster>10</hamster> 
    <squirrel>15</squirrel> 
    <porcupine>1</porcupine> 
    <beaver>2</beaver> 
</count> 

或可替換地(少preferrable)有輸出是這樣的:

<count> 
    <!-- file_id comes here later --> 
    <kangaroo>25</kangaroo> 
    <giraffe>10</giraffe> 
    <sp> 
    <name>hamster</name> 
    <number>10</number> 
    </sp> 
    <sp> 
     <name>squirrel</name> 
     <number>15</number> 
    </sp> 
    <sp> 
     <name>porcupine</name> 
     <number>1</number> 
    </sp> 
    <sp>  
     <name>beaver</name> 
     <number>2</number> 
    </sp> 
</count> 

我怎麼能使用XQuery實現這一目標?

更新3(和今晚的最後一次更新:-)): 如果我打破從XML輸出拿走並使用CSV輸出,看來我現在有解決方案。

查詢:

let $nl := "&#10;" 
for $z in /ZOO, $m in $z/Mammals 
return 
(
    string(
    concat 
    (
    'kangaroo', ';', $m//kangaroo/number/text(),$nl, 
    'giraffe', ';', $m//giraffe/number/text(), $nl 
)), 

for $r in $m//rodent 
return 
( 
if ($r//name/text()) then 
string(concat($r//name/text(), ';', $r//number/text(), $nl)) 
else 
string(concat($r//other_rodent_name/text(), ';', $r//number/text(), $nl)) 
) 
) 

和輸出:

kangaroo;25 
giraffe;10 
    hamster;10 
    squirrel;15 
    porcupine;1 
    beaver;2 

其可以容易地進一步處理。

一個新的小問題在這裏:從哪裏來的縮進?非常感謝您的時間。

+0

提供的通緝結果缺少很多動物:羚羊,mouflon,麋鹿,ibex,...等,...請編輯問題並更正。 –

+0

對不起,我只是想保持輸出短。我只想說,袋鼠,長頸鹿,羚羊,毛夫隆等都有自己的標籤,而齧齒動物卻沒有。我的問題是輸出齧齒動物的數量。 –

+0

v_e,對不起,但目前形式的問題是模棱兩可和矛盾的 - 如果人們開始回答它,他們將不得不猜測,並且會有來自不同人的不同猜測 - 您會收到許多不同的答案,而且沒有他們可能碰巧是你想要的。所以回答這個問題對你或回答者都不好。 –

回答

1

在您的XML中識別「動物」的唯一方法是存在數字元素。

/ZOO//*[number] 

一旦我們選擇了一種動物,我們可以用這個方法來得到它的名字:

if (fn:exists($animal/name)) 
then $animal/name/fn:string(.) 
else 
    if (fn:exists($animal/other_rodent)) 
    then $animal/other_rodent/other_rodent_name/fn:string(.) 
    else fn:local-name($animal) 

添加元素構造和與工會和序列運算替代嵌套的條件給了我們一個完整的例子:

element count { 
    for $animal in /ZOO//*[number] 
    let $name := 
    ($animal/(name|other_rodent/other_rodent_name)/text(), 
     fn:local-name($animal))[1] 
    let $number := $animal/number/fn:string(.) 
    return 
    element { fn:replace($name, " ", "_") } { 
     fn:concat("'", fn:concat($number, "'")) 
    } 
}