【问题标题】:How to convert text inside a node into child node using xquery update?如何使用 xquery 更新将节点内的文本转换为子节点?
【发布时间】:2014-02-01 00:03:19
【问题描述】:

我有一个类似的 xml 文档

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

如何使用所有节点转换此文档,这意味着如果节点包含 textchild node 使用 xquery-update 将文本转换为子节点(比如说 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

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

【问题讨论】:

  • 首先我可以创建带有值 text() 的节点“childtext”。现在我必须删除仍然存在的旧文本> 我不能只删除这个文本。如果我想让 value 为空,其他子节点也将被删除。
  • 这是我尝试做的: let $a := .... return copy $i := $a modify ( for $x in $i/descendant-or-self::* return ( if($x/text() and exists($x/*)) then ( insert node {$x/text()} as first into $x, (: 这里应该以某种方式删除此文本或更新到下一个级别:) ) else ( ) ) ) return $i
  • 请根据您的问题编辑此代码(此处难以阅读),并且不要省略部分代码,使其不再运行(let $a := .... 肯定没有工作代码)。您当前的代码有什么问题?
  • 完成!!请再次检查问题
  • @dirkk:如果帖子有问题,请详细描述问题,而不是仅仅发布“你试过什么”。请参阅this Meta post,了解“您尝试过什么”cmets 是否可以接受以及“您尝试过什么”的替代方案。谢谢!

标签: xquery xquery-update


【解决方案1】:

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

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

【讨论】:

  • 是是是的,这就是我真正想要的 :-) 谢谢@dirkk :-)
  • 嗨 Dirkk 它只适用于一个文本()。这意味着它不会像 ab ab 那样工作。如何解决。
  • @PrakashThapa 我编辑了我的答案,尽管我确实看到了你的解决方案。我更新的答案通常比以前更好(将条件直接作为谓词放入 for 语句中)并且以这种方式尊重多个 text() 元素。我非常喜欢这种解决方案,因为它更易于阅读且性能更高。
【解决方案2】:

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

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

再次感谢您。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多