如何将属性添加到节点的所有特定子节点

时间:2022-09-26 08:00:24

I have the following node in which I want to add attribute to all add nodes.

我有以下节点,我想在其中添加属性到所有添加节点。

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

I tried

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

It can add the attribute to the test node. But

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

When I tried

当我尝试

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

It added the attribute to the first add node but returns only add node with added attribute. Then when I tried with $test//add it throws error.

它将属性添加到第一个添加节点,但仅返回添加了属性的添加节点。然后,当我尝试使用$ test //添加它时抛出错误。

When I tried

当我尝试

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

It returns two add nodes individually. Now, how to restructure the original node to add the attributes to only the specified nodes.

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

2 个解决方案

#1


5  

First, let me point out that there is a difference in how this is done for just in-memory use versus updating the content of the database. For the latter, you could do:

首先,我要指出,仅仅在内存中使用与更新数据库内容的方式有所不同。对于后者,您可以这样做:

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

To change it in memory, which is what functx does, you'll be making a copy of the original, making changes in the copy as you build it. This is called recursive descent and is a pretty common pattern. I wrote a blog post a while ago that shows how to implement recursive descent, but essentially you'll do a typeswitch that, when it encounters an "add" element, creates the new attribute. You can use the functx function for that. Something along these lines (untested):

要在内存中更改它,这就是functx所做的,您将制作原始副本,在构建副本时对副本进行更改。这称为递归下降,是一种非常常见的模式。我刚才写了一篇博客文章,展示了如何实现递归下降,但实质上你会做一个类型切换,当它遇到“add”元素时,会创建新属性。你可以使用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 
};

This code assumes that an add element won't have add elements inside of it; if you will, then you'd want to do something like the second case for the first.

此代码假定add元素不会在其中添加元素;如果你愿意,那么你想做第一种情况的第二种情况。

#2


2  

Well you can replace/insert/delete an element or attribute in two ways. In-memory change or changing the actual content of the database. Since you do not want to change the value in DB, you can use in-memory document updation.

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

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

“/MarkLogic/appservices/utils/in-mem-update.xqy”中的import module namespace mem =“http://xqdev.com/in-mem-update”;

Instead of using xdmp:node-insert-child() you can use mem:node-insert-child(<x/>, <y/>)

您可以使用mem:node-insert-child( , )而不是使用xdmp:node-insert-child()

#1


5  

First, let me point out that there is a difference in how this is done for just in-memory use versus updating the content of the database. For the latter, you could do:

首先,我要指出,仅仅在内存中使用与更新数据库内容的方式有所不同。对于后者,您可以这样做:

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

To change it in memory, which is what functx does, you'll be making a copy of the original, making changes in the copy as you build it. This is called recursive descent and is a pretty common pattern. I wrote a blog post a while ago that shows how to implement recursive descent, but essentially you'll do a typeswitch that, when it encounters an "add" element, creates the new attribute. You can use the functx function for that. Something along these lines (untested):

要在内存中更改它,这就是functx所做的,您将制作原始副本,在构建副本时对副本进行更改。这称为递归下降,是一种非常常见的模式。我刚才写了一篇博客文章,展示了如何实现递归下降,但实质上你会做一个类型切换,当它遇到“add”元素时,会创建新属性。你可以使用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 
};

This code assumes that an add element won't have add elements inside of it; if you will, then you'd want to do something like the second case for the first.

此代码假定add元素不会在其中添加元素;如果你愿意,那么你想做第一种情况的第二种情况。

#2


2  

Well you can replace/insert/delete an element or attribute in two ways. In-memory change or changing the actual content of the database. Since you do not want to change the value in DB, you can use in-memory document updation.

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

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

“/MarkLogic/appservices/utils/in-mem-update.xqy”中的import module namespace mem =“http://xqdev.com/in-mem-update”;

Instead of using xdmp:node-insert-child() you can use mem:node-insert-child(<x/>, <y/>)

您可以使用mem:node-insert-child( , )而不是使用xdmp:node-insert-child()