2015-11-17 162 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/>)

相關問題