在 XQuery 中修饰 XML 数据源

Embellish XML datasource in XQuery

我正在使用实现 XQuery 3.0 的 BaseX。

如何在 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>

但是当我有很多元素必须重复时,这很快就会变得乏味。有没有一种方法可以得到这个结果,而不必输入我想在结果集中保留的所有属性和元素?

当然可以! XQuery 非常强大。更好的是,BaseX 不仅支持 XQuery 3.0,而且还支持 XQuery 更新,我想这在这里更为相关。

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
)

当然,根据你的元素是如何重复的(这从你的问题中很清楚),你现在可以用它来,例如在适当的地方递归地插入这样的节点。这样做的另一个提示:如果你想动态 select 一个元素,有时需要写成 /X 更好 /*[local-name() = 'X'] 因为现在元素名称不必是静态的.