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 中识别“动物”的唯一方法是数字元素的存在。

/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 回答