2015-11-17 4 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, но по существу вы будете делать typwitch, который, когда он встречает элемент «добавить», создает новый атрибут. Для этого вы можете использовать функцию 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

Я не хочу, чтобы изменить значение в БД. Я хочу получить значение, и я хочу реструктурировать его с помощью некоторых пользовательских атрибутов и представить его для преобразования. Я попробовал второй подход, но строка $ node/node()! local: change (.) вызывает ошибку. Я не уверен в использовании оператора «!». Это ошибка «Неожиданная синтаксическая ошибка маркера, неожиданный Junk_, ожидающий Comma_ или Rbrace_». Я пытался изменить его разными способами, но он не работает. Ответьте, пожалуйста. Я также попытаюсь заставить его работать. – Karthick

+0

Какую версию MarkLogic вы используете? «!» оператор является относительно новым. Вы можете заменить эту строку 'for $ n в $ node/node() 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/>)

Смежные вопросы