如何在XSLT的for-each/select中移除仅含 的标签?
这个问题的核心在于** 对应的是Unicode非断空格(U+00A0)**,而XSLT默认的normalize-space()函数只会处理普通空格(U+0020)、制表符、换行符这类空白字符,不会识别U+00A0——所以你之前尝试的normalize-space(.) != ''这类条件才会失效,仅含 的节点经过normalize-space()后依然会返回U+00A0,不是空字符串。
下面给你两种可行的解决方案,适配不同版本的XSLT环境:
方案1:兼容XSLT 1.0(通用方案)
使用translate()函数把U+00A0转换成普通空格,再用normalize-space()判断是否为空。把这个条件加到你的原有选择器中即可:
//*[local-name()='p' and following-sibling::*[local-name()='p']/*='Header 3' and preceding-sibling::*[local-name()='p']/*='Header 2' and normalize-space(translate(., ' ', ' ')) != '']
解释:translate(., ' ', ' ')会把所有非断空格替换成普通空格,之后normalize-space()会去掉首尾空白并合并中间空白,如果替换后内容为空,说明原节点仅含 (或 加其他空白),就会被排除。
方案2:XSLT 2.0及以上(更简洁)
如果你的环境支持XSLT 2.0+,可以用正则表达式直接匹配仅含 (及可选空白)的节点,用not()函数排除它们:
//*[local-name()='p' and following-sibling::*[local-name()='p']/*='Header 3' and preceding-sibling::*[local-name()='p']/*='Header 2' and not(matches(., '^\s*\xA0\s*$'))]
这里的正则^\s*\xA0\s*$表示:字符串从开头到结尾,只能是任意数量的空白字符(包括普通空格、换行等)加上一个非断空格,符合这个规则的节点会被排除。
测试效果
应用上述条件后,你的for-each循环只会选中那两个有实际文本内容的<p>节点,输出的XML会变成:
<mylabel> Lorem ipsum. </mylabel> <mylabel> More lorem ipsum. </mylabel>
内容的提问来源于stack exchange,提问作者Yampeku
相关产品推荐
相关产品推荐

