如何修改XSLT模板保留attr属性中b值非空的元素?
问题:调整XSLT以保留特定属性非空的元素
我之前编写了一段XSLT,用于移除所有空元素及其父元素,但perm元素无论是否为空都必须保留。现在需要修改这段代码,实现保留attr属性中b值非空的元素,尝试使用contains函数但未得到预期效果。
原XSLT代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="*[not(self::perm)][not(descendant::text()[normalize-space()])]" /> </xsl:stylesheet>
源XML
<?xml version="1.0" encoding="UTF-8"?> <item> <perm desc="item_1" attr="a='';b=''"> <content> <notuse></notuse> </content> <desc>Item 1</desc> <details> <firstname desc="Name" attr="a='';b=''">John</firstname> <lastname desc="Last" attr="a='';b=''"></lastname> <phone desc="phone" attr="a='';b='561-663-1254'"></phone> </details> </perm> <perm desc="item_2" attr="a='';b=''"></perm> </item>
预期结果
<item> <perm desc="item_1" attr="a='';b=''"> <desc>Item 1</desc> <details> <firstname desc="Name" attr="a='';b=''">John</firstname> <phone desc="phone" attr="a='';b='561-663-1254'"></phone> </details> </perm> <perm desc="item_2" attr="a='';b=''"></perm> </item>
解决方案
调整后的XSLT代码
要实现需求,需要修改匹配空元素的模板,增加对attr属性中b值的判断逻辑,排除那些b值非空的元素。
方法一:使用contains快速判断
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 仅移除:非perm元素、无空文本后代、且attr中b值为空的元素 --> <xsl:template match="*[ not(self::perm) and not(descendant::text()[normalize-space()]) and contains(@attr, 'b=''') ]" /> </xsl:stylesheet>
方法二:精准提取b值判断(更严谨)
如果需要更精准的判断,可以通过字符串截取提取b的值:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 提取b的值,判断是否为空字符串 --> <xsl:template match="*[ not(self::perm) and not(descendant::text()[normalize-space()]) and substring-before(substring-after(@attr, 'b='), ';') = '''' ]" /> </xsl:stylesheet>
逻辑说明
- 原模板仅判断元素是否有非空文本后代,现在新增了
attr属性的检查:- 方法一通过
contains(@attr, 'b=''')判断元素的b值是否为空,仅移除符合条件的空元素; - 方法二通过
substring-after和substring-before精准提取b的取值,判断是否为空字符串,避免属性值中出现类似b='';xxx的误判。
- 方法一通过
内容的提问来源于stack exchange,提问作者Somebody
相关产品推荐
相关产品推荐

