我尝试使用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 := " "
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 :(得分: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)
添加元素构造函数并使用union和sequence操作替换嵌套条件为我们提供了一个完整的示例:
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, "'"))
}
}