1

xQuery を使用して複数の XML ファイルを処理しようとしています (これまでの経験は非常に限られています)。XML の重要な部分は、次のように表すことができます。

<?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>、各ファイルにはさまざまなげっ歯類があります。

ファイルの監査を行う私の試みは次のようになります (私は 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>

つまり、回避策として対応する番号を使用してげっ歯類 (ハムスター、リス、ヤマアラシ、ビーバー) を出力し、後で出力を編集することもできます。こちらです:

 <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>

または、代わりに(あまり好ましくない)出力を次のようにすることもできます。

 <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

さらに簡単に処理できます。

ここで新しい小さな質問: インデントはどこから来るのですか? お時間をいただきありがとうございました。

4

1 に答える 1

1

XML で「動物」を識別する唯一の方法は、number 要素の存在です。

/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, "'"))
    }
}
于 2013-12-13T21:35:18.327 に答える