我想为每个pair
添加额外的对
我有这样的代码:
<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>
我需要在每对之后插入其他对,无论在哪个级别,前缀:“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>
要获得这种结果,我需要使用函数:node-name()
?它是如何工作的?我应该如何使用它?也许我应该使用另一种功能?
答案 0 :(得分:1)
正如@ 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>
更新 - 正如您在评论中提到的那样,只会复制最外面的对,如果您想复制所有对,无论它们的深度如何,那么您需要使用递归下降来转换输入。
我实际上发现在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())
recursive-descent
函数基本上通过节点树进行从左到右的递归下降。它传递给pair
函数的任何名为copy-pair
的元素,否则它只会复制除$copying
内文本节点的副本(value
)之外的所有内容element,在这种情况下,它为副本创建一个新的替代文本值。
copy-pair
函数决定是否复制原始对,具体取决于我们是否已经复制,然后创建原始对的新副本,然后它本身执行递归下降。
答案 1 :(得分:-1)
如果您可以访问XQuery update和转换表达式,则可以执行以下操作:
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
};