使用XSLT移除XML空标签(含空白字符的标签除外)
XML移除空标签后残留空行的原因及解决办法
问题场景
需要用XSLT移除XML里**完全无内容(连空白字符都没有)**的空标签,保留包含空白字符的标签,同时不打乱原有格式。
源XML
<inRoot> <t1></t1> <t2> </t2> <t3>World</t3> </inRoot>
期望输出
<inRoot> <t2> </t2> <t3>World</t3> </inRoot>
尝试的XSLT代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml"/> <xsl:strip-space elements=""/> <xsl:template match="/"> <xsl:apply-templates select="*"/> </xsl:template> <xsl:template match="*"> <xsl:if test=".!=''"> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:apply-templates/> </xsl:copy> </xsl:if> </xsl:template> </xsl:stylesheet>
实际输出(存在问题)
<inRoot> <t2> </t2> <t3>World</t3> </inRoot>
空行残留的原因
空行留在那是因为两个核心问题:
- 你的模板只处理了元素节点(
match="*"),完全没管文本节点。<t1>所在行的缩进空白(比如那行的四个空格+换行)是<inRoot>的子文本节点,当<t1>被移除后,这个空白文本节点就单独留了下来,最终渲染成空行。 <xsl:strip-space elements=""/>的写法无效——它不是全局剥离所有空白,而是仅剥离未指定preserve-space的元素内的空白,这里没指定具体元素,导致<inRoot>下的空白文本节点没被处理。
另外,判断条件.!=''也有漏洞:它检查元素的字符串值,<t2>的字符串值是空格(非空)所以能保留,但<t1>的字符串值是空会被过滤,可它周围的空白文本节点没被清理。
解决办法
要同时处理元素节点和文本节点,确保无用的空白文本节点被清理,同时保留<t2>里的有意义空白。
简洁版XSLT代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <!-- 剥离所有元素内的纯空白文本节点 --> <xsl:strip-space elements="*"/> <!-- 保留包含空白字符的元素内的空白 --> <xsl:preserve-space elements="*[text()[normalize-space(.) = '']]"/> <!-- 直接匹配并移除完全空的元素(无内容、无空白、无子节点) --> <xsl:template match="*[normalize-space(.) = '' and not(text())]"/> <!-- 默认模板:复制所有其他节点(属性、文本、有效元素等) --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
代码说明
<xsl:strip-space elements="*"/>:全局剥离所有元素内的纯空白文本节点,包括<inRoot>下原本<t1>所在行的缩进空白。<xsl:preserve-space elements="*[text()[normalize-space(.) = '']]"/>:专门保留那些内部只有空白字符的元素(比如<t2>)里的空白,避免被误删。- 匹配规则
*[normalize-space(.) = '' and not(text())]:精准匹配完全空的元素——既没有非空白内容,也没有任何文本节点(包括空白),直接跳过不复制,也就是移除这类标签。
这样处理后,<t1>会被彻底移除,同时它所在行的空白也会被清理,不会留下空行,<t2>和<t3>都能按预期保留,格式完全符合要求。
内容的提问来源于stack exchange,提问作者Tppi
相关产品推荐
相关产品推荐

