在XQuery中修饰XML数据源

时间:2016-03-26 14:47:07

标签: xquery basex

我正在使用BaseX,它实现了XQuery 3.0。

如何在XQuery中修饰XML数据源,而不必键入我想要包含的所有元素?例如,请考虑以下XML:

<X>
  <name>The root</name>
  <Y>
     <name> Level 1</name>
     <Z>
         <name>Level 2a</name>
         <value>1</value>
     </Z>
  </Y>
  <Y>
     <name>Level 1b</name>
     <Z>
         <name>Level 2b</name>
         <value>2</value>
     </Z>
  </Y>
</X>

我想在每个级别添加所有值的总和,如下所示:

<X>
  <name>The root</name>
  <value>3</value>
  <Y>
     <name> Level 1</name>
     <value>1</value>
     <Z>
         <name>Level 2a</name>
         <value>1</value>
     </Z>
  </Y>
  <Y>
     <name>Level 1b</name>
     <value>2</value>
     <Z>
         <name>Level 2b</name>
         <value>2</value>
     </Z>
  </Y>
</X>

我可以使用这样的XQuery:

for $x in /X
return
<X>{
  $x/name,
  <value>{sum($x//value)}</value>,
  for $y in $x/Y
  return
  <Y>{
    $y/name,
    <value>{sum($y//value)}</value>,
    $y/Z
  }</Y>
}</X>

但是当我有很多元素需要重复时,这会非常繁琐。有没有办法获得这个结果而不必输入我想要保留在结果集中的所有属性和元素?

1 个答案:

答案 0 :(得分:2)

当然可以! XQuery非常强大。更棒的是,BaseX不仅支持XQuery 3.0,还支持XQuery Update,我猜这里更有意义。

XQuery本身只是一种查询语言。因此,如果要在某些位置插入元素,则必须像在示例中一样重新创建整个元素。但是,XQuery Update添加了实际更新文档的构造,例如您可以使用它来更新数据库中的值。如果您只想在本地转换值,则可以使用transform expression

由于规范中的构造非常庞大,我们引入了特定于BaseX的关键字update,您可以使用它来转换XML文档。

因此,使用此查询可能如下所示:

./X update (
  insert node <value>{sum(.//value)}</value> after ./name,
  for $y in ./Y
  return insert node <value>{sum($y//value)}</value> after $y/name
)

当然,根据您的元素重复的方式(从您的问题中可以清楚地看出),您现在可以将其用于例如递归地在适当的位置插入这样的节点。还有一个提示:如果你想动态选择一个元素,有时需要编写而不是/X更好/*[local-name() = 'X'],因为现在元素名称不一定是静态的。