这是我的xml示例。
let $test :=
<root>
<a z="">stuff</a>
<b z="12" y="">more stuff</b>
<c>stuff</c>
<d z = " " y="0" x ="lkj">stuff goes wild</d>
</root>
我想使用查询删除空属性来获取此信息:
<root>
<a>stuff</a>
<b z="12">more stuff</b>
<c>stuff</c>
<d y="0" x ="lkj">stuff goes wild</d>
</root>
我已经用我的查询得到了这么多,但是我不能让它只删除空属性,而不是删除所有属性,如果元素中有任何空属性。
declare function local:sanitize ($nodes as node()*) {
for $n in $nodes
return typeswitch($n)
case element() return
if ($n/@*[normalize-space()='']) then (element{node-name($n)} {($n/@*[.!=''], local:sanitize($n/node()))})
else (element {node-name($n)} {($n/@*, local:sanitize($n/node()))})
default return ($n)
};
该功能需要高效,因此我希望使用typeswitch。我觉得我很接近,但最后一步似乎让我望而却步。即。 z =&#34; &#34;没有被抓住。谢谢您的帮助。
答案 0 :(得分:2)
代码的问题在于,在重新创建元素时,您需要检查完全空的属性,而不是在空白规范化后检查空属性。加上这个,你就没事了。
if ($n/@*[normalize-space()='']) then (element{node-name($n)} {($n/@*[normalize-space(.)!=''], local:sanitize($n/node()))})
我简化了模式并区分了属性,元素和其他所有内容。过滤空属性,重新创建元素并返回其他任何内容。生成的函数更容易阅读和理解,并产生正确的输出:
declare function local:sanitize ($nodes as node()*) {
for $node in $nodes
return typeswitch($node)
(: filter empty attributes :)
case attribute() return $node[normalize-space(.)]
(: recreate elements :)
case element() return
element { node-name($node) } {
(: Sanitize all children :)
for $child in $node/(attribute(), node())
return local:sanitize($child)
}
(: neither element nor attribute :)
default return $node
};