2015-11-17 127 views
3

我有以下节点,我想在其中添加属性到所有add节点。如何将属性添加到节点的所有特定子节点

<test> 
    <add>x1</add> 
    <c><add>x2</add></c> 
    <b att1="x">x</b> 
</test> 

我试图

functx:add-attributes($test, xs:QName('att1'), 1) 

它可以将属性添加到test节点。但

当我试图

functx:add-attributes($test/add, xs:QName('att1'), 1) 

它添加的属性到第一附加节点,但仅返回添加的属性添加节点。然后当我尝试$test//add它会引发错误。

当我试图

for $add in $test//add 
    return functx:add-attributes($add, xs:QName('att1'), 1) 

它返回两个单独添加节点。现在,如何重构原始节点以仅将属性添加到指定的节点。

回答

5

首先,我要指出的是,对于仅使用内存使用而不是更新数据库内容的做法,存在差异。对于后者,你可以这样做:

for $add in $test//add 
return 
    xdmp:node-insert-child(
    $add, 
    attribute atta1 { 1 } 
) 

要改变它在内存中,这是functx做什么,你会使得原有的副本,为你打造它使得在副本中的变化。这被称为递归下降,是一个很常见的模式。我前一段时间写了一篇博客文章,其中显示how to implement recursive descent,但本质上你会做类型切换,当它遇到“添加”元素时,会创建新属性。你可以使用functx函数。沿着这些线的东西(未经测试):

declare function local:change($node) 
{ 
    typeswitch($node) 
    case element(add) return 
     functx:add-attributes($node, xs:QName('att1'), 1) 
    case element() return 
     element { fn:node-name($node) } { 
     $node/@*, 
     $node/node() ! local:change(.) 
     } 
    default return $node 
}; 

此代码假定添加元素不会在其中添加元素;如果你愿意的话,那么你会想要像第二个案例那样做。

+0

我不想改变DB值。我想获得价值,我想用一些自定义属性重构它,并将其呈现给转换。我尝试了第二种方法,但是$ node/node()!本地:更改(。)抛出错误。我不确定操作符“!”的用法。这是错误“意外的标记语法错误,意外的垃圾_,期待Comma_或Rbrace_”。我试着用很多方式改变它,但它不起作用。请回复。我也会努力让它工作。 – Karthick

+0

您使用的是什么版本的MarkLogic? “!”运营商相对较新。你可以在$ node/node()中用'for $ n替换那行。return local:change($ n)' –

+0

非常感谢你,它工作正常。在办公室我们使用ML7。我在我家ML5的地方试过这个样品。在ML7中它正在工作。 – Karthick

2

那么你可以用两种方法替换/插入/删除元素或属性。 内存中的更改或更改数据库的实际内容。 由于您不想更改数据库中的值,因此可以使用内存中的文档更新。

import module namespace mem = "http://xqdev.com/in-mem-update" at "/MarkLogic/appservices/utils/in-mem-update.xqy";

而不是使用xdmp:node-insert-child()可以使用 mem:node-insert-child(<x/>, <y/>)

相关问题