XQuery获取节点的位置仅相对于具有相同标记名

时间:2018-04-10 03:20:31

标签: xml list position xquery basex

我正在尝试向XQuery中与其位置对应的标记添加属性,但仅涉及相同标记名称的兄弟。具体来说,列表中的项目。所以这里有2个潜在的查询输出:

<list>
    <title>foo</title>
    <item>bar1</item>
    <item>bar2</item>
</list>

 <list>
     <item>bar1</item>
     <item>bar2</item>
</list>

对于两者,这是添加属性时所需的结果:

<list>
    <title>foo</title>
    <item position="1">bar1</item>
    <item position="2">bar2</item>
</list>

 <list>
     <item position="1">bar1</item>
     <item position="2">bar2</item>
</list>

我正在使用的当前查询是:

count($item/preceding-sibling::*)+1

但是,计数包括每个标记,而不仅仅是item个标记。所以在上面带有title标签的例子中,它会计算,所以我得到:

<list>
    <title>foo</title>
    <item position="2">bar1</item>
    <item position="3">bar2</item>
</list>

我尝试了一些方法,例如减去列表中没有item标记名称的所有子项的计数,例如:

    count($item/preceding-sibling::*)+1-count($list/*[local-name() != 'item'])

和其他一些类似的方法但无济于事。我怎样才能做到这一点?

编辑:

以下是我如何做的背景示例。输入数据:

<LIST1>
    <TITLE>REASON FOR REVISION</TITLE>
    <L1ITEM KEY="L1I10254244923043">
        <PARA>Summary - Background: Updated and added related references.</PARA>
    </L1ITEM>
    <L1ITEM KEY="L1I20300231297755">
        <PARA>Summary - Action: Updated to add more work and new groups and configurations.</PARA>
    </L1ITEM>
</LIST1>

然后我将LIST1根元素传递给这个函数:

declare function local:listx($listx as element()){
   <list level="{substring(name($listx),5)}">
   {
     for $lxitem in $listx/*
     return if (name($lxitem) = "TITLE") then (
       <title>{local:concatText($lxitem)}</title>
     )
     else local:extract($lxitem, "item", [
       ["position", count($lxitem/preceding-sibling::*)+1]
     ])
   }
   </list>
};

concatText函数只是将所有文本与空格分隔符连接在一起,没有问题。 extract()功能如下:

declare function local:extract(
  $root as element(), $tag as xs:string, $props as array(*)
) {
  element {$tag}{

    for $prop at $i in $props
    where array:size($prop) != 0
    return attribute {$props($i)(1)} {$prop($i)(2)},

    for $child in $root/*
    return switch(name($child))
      case "TXTGRPHC" return local:plaintext($child)
      case "PARA" return local:plaintext($child)
      case ...
      default return ()

  }
};

作为旁注,我在这里添加属性的方式,整个2D数组$props,只会添加第一个属性,其余的被忽略。虽然这是另一个问题。

1 个答案:

答案 0 :(得分:2)

在使用BaseX时,您可以使用XQuery Update http://docs.basex.org/wiki/XQuery_Update,例如

copy $items := <root>
<list>
    <title>foo</title>
    <item>bar1</item>
    <item>bar2</item>
</list>

 <list>
     <item>bar1</item>
     <item>bar2</item>
</list>
</root>
modify (
for $item in $items/list/item
return insert node attribute {'id'} {count($item/(., preceding-sibling::item))} into $item
)
return $items

结果是

<root>
  <list>
    <title>foo</title>
    <item id="1">bar1</item>
    <item id="2">bar2</item>
  </list>
  <list>
    <item id="1">bar1</item>
    <item id="2">bar2</item>
  </list>
</root>