1

这是我的 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。我觉得我很接近,但最后一步似乎躲过了我。IE。z = " " 不会被抓住。谢谢您的帮助。

4

1 回答 1

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
};
于 2014-09-14T18:53:16.823 回答