鉴于此XML片段:
<root> <!-- $root points here -->
<!-- ... -->
<A visible="true">
<B visible="false">
<C visible="true"/> <!-- but effectively false! -->
</B>
<D visible="true">
<E visible="true" />
<F visible="false" />
</D>
</A>
<!-- ... -->
</root>
运行查询$root//A
会给我A
及其所有后代。到目前为止一切都很好。
我想要的是用谓词来过滤A
的后代,比如说[@visible=true]
。我希望查询返回
<A visible="true">
<D visible="true">
<E visible="true" />
</D>
</A>
相反,即。过滤掉与谓词不匹配的所有子元素(或其父元素与其不匹配)。
考虑一个像上面描述的XML系统的GUI系统,在渲染它时我可以在树中过滤可见元素。
我认为这对于XSLT来说是微不足道的,但我一定会使用XQuery。
答案 0 :(得分:2)
它可以在XQuery中完成而不需要太多努力。只需要一个函数递归重写限定节点,同时应用过滤器:
declare function local:rewrite($node as node()) as node()?
{
typeswitch ($node)
case element() return
if (local:filter($node)) then
element {node-name($node)}
{
$node/@*,
for $child in $node/node() return local:rewrite($child)
}
else
()
default return
$node
};
declare function local:filter($node as element()) as xs:boolean
{
$node/@visible
};
然后使用路径表达式选择A并将函数应用于结果:
for $a in $root//A return local:rewrite($a)
该函数使用一种通用模式来使用XQuery来处理所谓的XSLT任务。事实上,我认为这样做也是非常可以接受的。就我而言,我感谢不必在这里留下XQuery符号的好处......
答案 1 :(得分:1)
您可以使用XQuery Update执行此操作并删除所有不可见的内容:
copy $c:=$root
modify delete node $c//*[@visible="false"]
return $c