如何用XSLT批量移除XML中所有以_#结尾的节点值?
解决XML中任意节点移除_#后缀的通用XSLT方案
你的问题核心是原来的XSLT依赖硬编码的节点路径,无法通用处理所有符合_数字结尾的节点值。要实现通用处理,我们可以利用XSLT的身份转换模板(默认复制所有节点),再添加一个针对文本节点的匹配模板,专门处理符合规则的内容。
核心思路
- 用身份转换模板保留XML的结构和所有未匹配的内容
- 匹配所有文本节点,检查其值是否以
_加数字结尾 - 对符合规则的文本,移除最后的
_数字后缀;不符合的则原样保留
方案一:XSLT 2.0+(推荐,更简洁)
如果你的处理器支持XSLT 2.0或更高版本,直接用正则表达式就能轻松实现:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 身份转换模板:默认复制所有节点和属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 匹配所有文本节点,处理_数字结尾的情况 --> <xsl:template match="text()[matches(., '_[0-9]+$')]"> <!-- 移除最后的_数字后缀 --> <xsl:value-of select="replace(., '_[0-9]+$', '')"/> </xsl:template> </xsl:stylesheet>
方案二:XSLT 1.0兼容版
如果只能用XSLT 1.0,我们可以改造你现有的lastUnderscore模板,让它能处理任意文本节点:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 身份转换模板 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 匹配所有文本节点,检查是否以_数字结尾 --> <xsl:template match="text()[contains(., '_') and number(substring-after(., '_')) = number(substring-after(., '_'))]"> <xsl:call-template name="removeTrailingUnderscoreNumber"> <xsl:with-param name="text" select="."/> </xsl:call-template> </xsl:template> <!-- 递归模板:移除最后的_数字后缀 --> <xsl:template name="removeTrailingUnderscoreNumber"> <xsl:param name="text"/> <xsl:choose> <!-- 检查最后一段是否是数字 --> <xsl:when test="contains($text, '_') and number(substring-after($text, '_')) = number(substring-after($text, '_'))"> <xsl:call-template name="removeTrailingUnderscoreNumber"> <xsl:with-param name="text" select="substring-before($text, '_')"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$text"/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
测试示例
用你提供的XML输入:
<trades> <tradeBody> <bond> <securityId> <securityAlternateCodes/> <securityLabel>179965</securityLabel> <securityMarket>CAD QC</securityMarket> <securityDisplayLabel>Q 3.5 120148_1</securityDisplayLabel> </securityId> <displayLabel>Q 3.5 120148_1</displayLabel> </bond> </tradeBody> </trades>
处理后输出:
<trades> <tradeBody> <bond> <securityId> <securityAlternateCodes/> <securityLabel>179965</securityLabel> <securityMarket>CAD QC</securityMarket> <securityDisplayLabel>Q 3.5 120148</securityDisplayLabel> </securityId> <displayLabel>Q 3.5 120148</displayLabel> </bond> </tradeBody> </trades>
关键改进点
- 不再依赖硬编码的节点路径,所有文本节点只要符合
_数字结尾规则都会被处理 - 保留了原XML的完整结构,不会破坏其他节点或属性
- 两种方案分别适配不同版本的XSLT处理器,灵活度更高
内容的提问来源于stack exchange,提问作者gapaso5652
相关产品推荐
相关产品推荐

