Function XQuery node-name()函数,它是如何工作的?

Function XQuery node-name()函数,它是如何工作的?,function,xquery,Function,Xquery,我想为每个对添加额外的对 我有这样的代码: <data> <pair> <key>keyName1</key> <value>something1</value> </pair> <pair> <key>keyName2</key> <value>something2</value> </pair> <p

我想为每个
对添加额外的对

我有这样的代码:

<data>
<pair>
    <key>keyName1</key>
    <value>something1</value>
</pair>
<pair>
    <key>keyName2</key>
    <value>something2</value>
</pair>
<pair>
    <key>keyName3</key>
    <value>
            <listOfPairs>
                <pair>
                    <key>keyName4</key>
                    <value>Something6</value>
                </pair>
            </listOfPairs>
    </value>
</pair>
<pair>
    <key>keyName5</key>
    <value>Something9</value>
</pair>
</data>

关键字1
有些事
关键字2
什么
关键字3
关键字4
什么
关键字5
有些事
我需要在每对之后插入其他对,无论在哪个级别,前缀为“copy”,值不同:

<data>
<pair>
    <key>keyName1</key>
    <value>something1</value>
</pair>
<pair>
    <key>copy_keyName1</key>
    <value>another1</value>
</pair>
<pair>
    <key>keyName2</key>
    <value>something2</value>
</pair>
<pair>
    <key>copy_keyName2</key>
    <value>another2</value>
</pair>
<pair>
    <key>keyNamedwithLists</key>
    <value>
        <listOfPairs>
            <pair>
                <key>keyName4</key>
                <value>Something6</value>
            </pair>
            <pair>
                <key>copy_keyName4</key>
                <value>Another6</value>
            </pair>
        </listOfPairs>
    </value>
</pair>
<pair>
    <key>keyName5</key>
    <value>Something9</value>
</pair>
<pair>
    <key>copy_keyName5</key>
    <value>another9</value>
</pair>
</data>

关键字1
有些事
复制密钥名1
另一个1
关键字2
什么
复制密钥名2
另一个2
关键字名称列表
关键字4
什么
复制密钥名4
另一个6
关键字5
有些事
复制密钥名5
另一个9

为了得到这种结果,我需要使用函数:
node-name()
?它是如何工作的?我应该如何使用它?或者我应该使用另一个函数?

正如@jens erat提到的,您不需要
node-name()
,相反,您可能需要这样的函数:

<data> {
for $pair in /data/pair
return
    ($pair,
    <pair>
        <key>{concat("copy_", $pair/key)}</key>
        <value>some other value</value>
    </pair>)
}</data>
{
对于$pair in/data/pair
返回
($对,
{concat(“复制”,$pair/key)}
其他价值
)
}
更新-正如您在评论中提到的,这将只复制最外层的对,如果您想复制所有对,而不管它们的深度如何,那么您需要使用递归下降来转换输入

实际上,我发现在XQuery中为您的特定用例编写这篇文章是一个相当大的挑战,尽管解决方案相当优雅,但我认为:-)如果其他人能想出更好的实现,我会感兴趣吗

xquery version "1.0";

declare function local:copy-pair($pair as element(pair), $copying) as element(pair)+ {
    (
        if(not($copying))then
            $pair
        else(),
        <pair>
            <key>{concat("copy_", $pair/key)}</key>
                { local:recursive-descent($pair/key/following-sibling::node(), true()) }
            </pair>
    )
};

declare function local:recursive-descent($nodes, $copying) {
    for $node in $nodes
    return
        (
        typeswitch($node)
            case element(pair) return
                local:copy-pair($node, $copying)

            case element() return
                element {node-name($node)} {
                    local:recursive-descent($node/node(), $copying)
                }

            case text() return
                if($copying and $node/parent::value and empty($node/parent::value/element()))then
                    text { concat("SOME NEW VALUE. old value = ", $node) }
                else
                    $node

            default return
                (
                    $node,
                    local:recursive-descent($node/node(), false())
                )
        )
};

local:recursive-descent(/data, false())
xquery版本“1.0”;
声明函数本地:复制对($pair作为元素(pair),$copying)作为元素(pair)+{
(
如果(不是($copying))那么
美元对
else(),
{concat(“复制”,$pair/key)}
{本地:递归下降($pair/key/following sibling::node(),true())}
)
};
声明函数本地:递归下降($nodes,$copying){
对于$node中的$node
返回
(
类型开关($node)
case元素(对)返回
本地:复制对($node,$copying)
case元素()返回
元素{node name($node)}{
局部:递归下降($node/node(),$copying)
}
case text()返回
如果($copying和$node/parent::value)为空($node/parent::value/element()),则
文本{concat(“一些新值。旧值=,$node)}
其他的
$node
默认返回
(
$node,
局部:递归下降($node/node(),false())
)
)
};
局部:递归下降(/data,false())
递归下降
函数基本上通过节点树执行从左到右的递归下降。任何名为
pair
的元素都会传递给
copy pair
函数,否则它只会复制
元素中文本节点的副本(
$copying
),在这种情况下,它会为副本创建一个新的可选文本值

copy pair
函数决定是否复制原始对,这取决于我们是否已经在复制,然后创建原始对的新副本,然后它本身执行递归下降。

如果您有权访问转换表达式,您可以执行以下操作:

declare function local:additional-pairs($d){
 copy $c:=$d
 modify(
   for $p in $c//pair[not(.//pair)] (: pairs with no descendant pairs :)  
   return insert node 
    <pair>
      <key>copy_{$p/key/string()}</key>
      <value>some new</value>
    </pair> 
   after $p
  )
  return $c
};
声明函数本地:附加对($d){
副本$c:=$d
修改(
对于$c//对中的$p[非(.//对)](:没有后代对的对:)
返回插入节点
复制{$p/key/string()}
一些新的
在$p之后
)
返回$c
};

node-name()
返回元素名称。对于
/node-name()
它将返回
foo
。我不明白您为什么需要它,因为您只需要访问值,而不需要访问元素名称。看起来不错,但当我放置映射时,我在data/pair[key=“keyNamedwithLists”]/value/listOfPairs/pair处获得了这一对。这一对没有任何副本。我需要那条终极之路,不管是哪条路,直到任何一对。每一对都应该得到一份。(添加:给定的映射是动态的,并且每次都会更改。)根据您的回答,他将只向那些添加additiona pairs:/data/pairy您还需要考虑pair的子级,其中值是一个对列表,可能您只需要$c//pairtanks上的谓词亚当,我做了更改。在示例中,keyName3没有在代码中复制(尽管keynameWithList变为keynamedWithList?)。