如何使用xquery update将节点内的文本转换为子节点?

时间:2014-01-13 09:41:37

标签: xquery xquery-update

我有一个像

这样的xml文档
<root>
  <first>
    First Level
    <second>
      second level
       <third>
         Third Level
       </third>
    </second>
    <second2>
      another second level
    </second2>
  </first>
</root>

如何使用所有节点转换此文档,这意味着如果节点包含textchild node使用xquery将文本转换为子节点(假设 childtext )更新

<root>
  <first>
    <childtext>First Level</childtext>
    <second>
      <childtext>second level</childtext>
       <third>
         Third Level
       </third> 
    </second>
    <second2>
      another second level
    </second2>
  </first>
</root>

以下是我的尝试:

let $a :=
<root>
  <first>
    First Level
    <second>
      second level
       <third>
         Third Level
       </third>
    </second>
    <second2>
      another second level
    </second2>
  </first>
</root>
return 
copy $i := $a
modify (
  for $x in $i/descendant-or-self::*
  return (
    if($x/text() and exists($x/*)) then (
      insert node <childtext>
        {$x/text()}
       </childtext> as first into $x
        (: here should be some code to delete the text only:)
    ) else ()
  )
)
return $i

我无法删除有兄弟节点的文本。

2 个答案:

答案 0 :(得分:3)

当您想要替换元素时,您应该只使用replace构造,而不是插入新元素并删除旧元素。对我来说似乎更简单:

copy $i := $a
modify (
  for $x in $i/descendant-or-self::*[exists(*)]/text()
  return replace node $x with <childtext>{$x}</childtext>
)
return $i

答案 1 :(得分:0)

修改后的解决方案来自@dirkk:

copy $i := $a
modify (
  for $x in $i/descendant-or-self::*
  return (
    if($x/text() and exists($x/*)) then (
      if(count($x/text())=1) then (
      replace node $x/text() with <child>    {$x/text()}</child>
      ) else (
        for $j at $pos in 1 to count($x/text())
        return 
       replace node $x/text()[$pos] with <child>{$x/text()[$pos]}</child>

    )


    ) else ()
  )
)
return $i

再次感谢你。