Xml 选择节点但忽略返回子节点的XQuery
我正在尝试创建一个xquery表达式,该表达式将返回选定的节点,但不会返回其子节点。这可能最好用一个例子来说明。我有以下myNode:Xml 选择节点但忽略返回子节点的XQuery,xml,xslt,xpath,xquery,Xml,Xslt,Xpath,Xquery,我正在尝试创建一个xquery表达式,该表达式将返回选定的节点,但不会返回其子节点。这可能最好用一个例子来说明。我有以下myNode: <myNode> <myElements id="1"> <myElement key="one">aaa</myElement> <myElement key="two" >bbb</myElement> <myElement key="three">
<myNode>
<myElements id="1">
<myElement key="one">aaa</myElement>
<myElement key="two" >bbb</myElement>
<myElement key="three">ccc</myElement>
</myElements>
<myElements id="2">
<myElement key="one">ddd</myElement>
<myElement key="two" >eee</myElement>
<myElement key="three">fff</myElement>
</myElements>
</myNode>
我找错树了吗?这在XPath/XQuery中可能吗?试试这个递归算法
xquery version "1.0";
declare function local:passthru($x as node()) as node()* { for $z in $x/node() return local:recurseReplace($z) };
declare function local:recurseReplace($x as node()) {
typeswitch ($x)
(: Changes based on a condition :)
case element(myElements) return <myElements id="{$x/@id}" />
(: IGNORE ANY CHANGES :)
case text() return $x
case comment() return comment {"an altered comment"}
case element() return element {fn:node-name($x)} {for $a in $x/attribute()
return $a, local:passthru($x)}
default return ()
};
let $doc :=
<myNode>
<myElements id="1">
<myElement key="one">aaa</myElement>
<myElement key="two" >bbb</myElement>
<myElement key="three">ccc</myElement>
</myElements>
<myElements id="2">
<myElement key="one">ddd</myElement>
<myElement key="two" >eee</myElement>
<myElement key="three">fff</myElement>
</myElements>
</myNode>
return local:recurseReplace($doc)
xquery版本“1.0”;
将函数local:passthru($x as node())声明为node()*{for$z in$x/node()返回local:recurseReplace($z)};
声明函数local:recurseReplace($x作为节点()){
打字开关($x)
(:基于条件的更改:)
case元素(myElements)返回
(:忽略任何更改:)
case text()返回$x
case comment()返回注释{“更改的注释”}
case element()返回元素{fn:node name($x)}{for$a in$x/attribute()
返回$a,本地:passthru($x)}
默认返回()
};
让$doc:=
aaa
bbb
ccc
ddd
eee
fff
返回本地:递归替换($doc)
对于这类任务,XQuery比XSLT差得多:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="myElements/node()"/>
</xsl:stylesheet>
<myNode>
<myElements id="1">
<myElement key="one">aaa</myElement>
<myElement key="two" >bbb</myElement>
<myElement key="three">ccc</myElement>
</myElements>
<myElements id="2">
<myElement key="one">ddd</myElement>
<myElement key="two" >eee</myElement>
<myElement key="three">fff</myElement>
</myElements>
</myNode>
<myNode>
<myElements id="1" />
<myElements id="2" />
</myNode>
在提供的XML文档上应用此转换时:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="myElements/node()"/>
</xsl:stylesheet>
<myNode>
<myElements id="1">
<myElement key="one">aaa</myElement>
<myElement key="two" >bbb</myElement>
<myElement key="three">ccc</myElement>
</myElements>
<myElements id="2">
<myElement key="one">ddd</myElement>
<myElement key="two" >eee</myElement>
<myElement key="three">fff</myElement>
</myElements>
</myNode>
<myNode>
<myElements id="1" />
<myElements id="2" />
</myNode>
aaa
bbb
ccc
ddd
eee
fff
生成所需的正确结果:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="myElements/node()"/>
</xsl:stylesheet>
<myNode>
<myElements id="1">
<myElement key="one">aaa</myElement>
<myElement key="two" >bbb</myElement>
<myElement key="three">ccc</myElement>
</myElements>
<myElements id="2">
<myElement key="one">ddd</myElement>
<myElement key="two" >eee</myElement>
<myElement key="three">fff</myElement>
</myElements>
</myNode>
<myNode>
<myElements id="1" />
<myElements id="2" />
</myNode>
解释:为myElements的子节点重写的标识规则XQuery只返回顶级节点,而不返回其子节点。但是返回的节点仍然连接到它们的子节点,无论显示结果的代码是什么,都会选择在实际选择的节点下显示完整的子树
因此,理解问题的第一步是认识到您不希望查询从源文档中选择节点,而是希望它通过具有不同的子节点来构造与原始节点不同的新节点
这意味着这是一种查询,您希望生成与原始文档相同但有一些小更改的结果文档。正如Dimitre所说,XSLT在这类问题上比XQuery好得多。但是,正如Scott所示,使用XQuery当然可以做到这一点。试试这是最短的方法
let $a :=
<myNode>
<myElements id="1">
<myElement key="one">aaa</myElement>
<myElement key="two" >bbb</myElement>
<myElement key="three">ccc</myElement>
</myElements>
<myElements id="2">
<myElement key="one">ddd</myElement>
<myElement key="two" >eee</myElement>
<myElement key="three">fff</myElement>
</myElements>
</myNode>
for $e1 in $a
return element {name($e1)}
{
for $e2 in $e1/*
return element{name($e2)}{$e2/@*}
}
let$a:=
aaa
bbb
ccc
ddd
eee
fff
在$a中的$e1
返回元素{name($e1)}
{
对于$e1中的$e2/*
返回元素{name($e2)}{$e2/@*}
}
问得好,+1。请参阅我的答案,以获得完整、简短且简单的XSLT解决方案:)您可以阅读Michael Kay在+1中发布的答案中对XQuery方法的看法。我同意XSLT是一种更适合此类任务的技术。