我需要使用XQuery向响应XML的元素添加属性。 以下面的XML作为输入,
<xyz:RootNode xmlns:abc="url1" xmlns:xyz="url2">
<abc:OtherNodes/>
<abc:messageHeader att1="val1" att2="val2">
<abc:childNodes/>
</abc:messageHeader>
<abc:OtherNodes/>
</xyz:RootNode>
需要一个Xquery添加一个属性 newAtt ,其值为 newVal ,并将结果显示为,
<xyz:RootNode xmlns:abc="url1" xmlns:xyz="url2">
<abc:OtherNodes/>
<abc:messageHeader att1="val1" att2="val2" newAtt="newVal">
<abc:childNodes/>
</abc:messageHeader>
<abc:OtherNodes>
</xyz:RootNode>
每次邮件头的属性数量可能会发生变化。因此查询应该添加一个新属性以及所有现有属性并返回整个文档。
答案 0 :(得分:2)
尝试以下方法:
xquery version "3.0";
module namespace foo="http://exist-db.org/apps/ns/foo";
declare function foo:process-node($node as node()?, $model as map()) {
if ($node) then
typeswitch($node)
case text() return $node
case element(messageHeader) return foo:messageHeader($node, $model)
default return element { $node/name() }
{ $node/@*, foo:recurse($node, $model) }
else ()
};
declare function foo:recurse($node as node()?, $model as map()) as item()* {
if ($node)
then
for $cnode in $node/node()
return foo:process-node($cnode, $model)
else ()
};
declare function foo:messageHeader($node as node(), $model as map()) {
element { $node/name() }
{ $node/@*,
attribute { 'newAtt' } { 'newVal' },
foo:recurse($node, $model)
}
};
然后在RootNode上调用foo:process-node
答案 1 :(得分:1)
你总是可以重复使用那里的轮子,XSLT。特别是如果您希望最大限度地降低代码中的风险。
eXist supports XSL Transformations以下是如何运行执行所需作业的XSLT转换的示例:
xquery version "3.0";
declare function local:add-attribute($input as node()?, $attributeName as xs:string, $attributeValue as xs:string?) {
let $xslt := <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template xmlns:abc="url1" match="abc:messageHeader">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="{$attributeName}">{$attributeValue}</xsl:attribute>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
return transform:transform($input, $xslt, ())
};
let $input := <xyz:RootNode xmlns:abc="url1" xmlns:xyz="url2">
<abc:OtherNodes/>
<abc:messageHeader att1="val1" att2="val2">
<abc:childNodes/>
</abc:messageHeader>
<abc:OtherNodes/>
</xyz:RootNode>
return local:add-attribute($input, "hey", "bam")
如果要将XSLT放入其自己的文件中,也可以使用$parameters
属性。将使事情变得更加可测试和模块化。