You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XSLT 1.0身份模板使用异常:过滤XML节点时丢失字段

问题描述

使用XSLT 1.0处理大型XML响应,需要移除部分无用字段,要求用apply-templates而非for-each。现有代码虽能移除无用字段,但匹配范围外的其他字段也消失了,是否错误使用了身份模板?

输入XML

<?xml version="1.0" encoding="UTF-8"?>
<xsl:object xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:array name="BankDetails">
<one>field1</one>
<two>field2</two>
<xsl:object>
<date>1234-56-78</date>
<Time>12345678</Time>
</xsl:object>
<xsl:object>
<date>0000-00-00</date>
<Time>00000000</Time>
</xsl:object>
<xsl:object>
<date>0000-00-00</date>
<Time>00000000</Time>
</xsl:object>
<xsl:object>
<date>0000-00-00</date>
<Time>00000000</Time>
</xsl:object>
<three>field3</three>
<four>field4</four>
<five>field5</five>
<six>field6</six>
</xsl:array>
</xsl:object>

原XSLT代码

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias"
xmlns:str="http://exslt.org/strings">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:namespace-alias stylesheet-prefix="axsl"   result-prefix="xsl" />
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
  <xsl:template match="xsl:object/xsl:array">    
        <xsl:for-each select="xsl:object[Time !='00000000']">
             <xsl:copy-of select = "."/>
        </xsl:for-each>  
  </xsl:template>
</xsl:stylesheet>

实际输出

<?xml version="1.0" encoding="UTF-8"?><xsl:object xmlns:xsl="http://www.w3.org/1999/XSL/Transform">    
    <xsl:object>        
        <date>1234-56-78</date>
         <Time>12345678</Time>
         </xsl:object>
</xsl:object>

期望输出

<?xml version="1.0" encoding="UTF-8"?>
<xsl:object xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:array name="BankDetails">
     <one>field1</one>
     <two>field2</two>
     <xsl:object>
         <date>1234-56-78</date>
         <Time>12345678</Time>
     </xsl:object>
     <three>field3</three>
     <four>field4</four>
     <five>field5</five>
     <six>field6</six>
 </xsl:array>
</xsl:object>    

问题分析与解决方案

你的身份模板本身没有错误,问题出在自定义的xsl:object/xsl:array模板上:

  • 这个模板直接覆盖了身份模板对<xsl:array>节点的处理逻辑,只输出了符合条件的<xsl:object>,完全忽略了<xsl:array>本身的复制,以及数组内的<one>、<two>、<three>等其他子节点,导致这些内容全部丢失。

正确的做法是只针对需要移除的节点编写匹配模板,让身份模板处理其余所有节点,完全不需要for-each:

  1. 保留身份模板,确保所有需要保留的节点(包括<xsl:array>、<one>、<two>等)都能被正常复制
  2. 新增一个模板,匹配那些需要移除的<xsl:object>节点(即xsl:array/xsl:object[Time='00000000']),模板内容为空,这样这些节点就会被自动跳过

修正后的XSLT代码

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias"
xmlns:str="http://exslt.org/strings">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl" />

<!-- 身份模板:复制所有未被特殊模板匹配的节点和属性 -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<!-- 匹配并移除Time为00000000的xsl:object节点 -->
<xsl:template match="xsl:array/xsl:object[Time='00000000']" />

</xsl:stylesheet>

效果验证

使用上述代码处理输入XML,将得到你期望的输出:<xsl:array>节点被完整保留,其中的<one>、<two>、<three>等字段全部保留,只有Time='00000000'的<xsl:object>被移除。


内容的提问来源于stack exchange,提问作者Mano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 04:50:33