说,我有一份文件 -
<something>
<parent>
<child>Bird is the word 1.</child>
<child>Curd is the word 2.</child>
<child>Nerd is the word 3.</child>
</parent>
<parent>
<child>Bird is the word 4.</child>
<child>Word is the word 5.</child>
<child>Bird is the word 6.</child>
</parent>
</something>
我想遍历文档并替换“#34; Bird&#34;用&#34;狗&#34;使用XQuery和MarkLogic API。到目前为止,我能够使用以下代码实现 -
let $doc := $DOC
return <something>
{for $d at $y in $doc/element()
let $p := <parent>
{for $c in $d/element()
let $child := if(fn:matches($c, "Bird")) then(<child>{fn:replace($c, "Bird", "Dog")}</child>) else($c)
return $child
}</parent>
return $p}
</something>
结果是
<something>
<parent>
<child>Dog is the word 1.</child>
<child>Curd is the word 2.</child>
<child>Nerd is the word 3.</child>
</parent>
<parent>
<child>Dog is the word 4.</child>
<child>Word is the word 5.</child>
<child>Dog is the word 6.</child>
</parent>
</something>
如果没有嵌套for循环,我怎样才能实现这一目标?之前曾问过这个问题,但使用的是XSLT。
答案 0 :(得分:4)
Write a function and use recursion. With the typeswitch
expression you can check node types at each stage of recursion, and using a computed element constructor您可以使用通用模板重建每个元素,而不知道其名称:
declare function local:transform(
$node as node()
) as node()*
{
typeswitch ($node)
case element() return element { node-name($node) } {
$node/@*,
for $n in $node/node()
return local:transform($n)
}
case text() return
if (matches($node, "Bird"))
then text { replace($node, "Bird", "Dog") }
else $node
default return $node
};
请注意,不必使用matches
显式检查,因为如果没有匹配项,replace
将返回输入字符串。
答案 1 :(得分:4)
来自wst的答案看起来非常好,但是经常会问同样的问题,他们创建了一个库来使这更容易。它通常被称为内存更新库&#39;。可在此处找到改进版本:
https://github.com/ryanjdew/XQuery-XML-Memory-Operations
我认为至少可以提一下它是值得的。
HTH!