XML处理求助:如何保留同名元素中的最后一个?XSLT实现问题
修复XSLT以保留每个Change节点下的最后一个Work元素
解决方案
使用以下XSLT即可实现需求:保留每个Change节点的所有属性和非Work子节点,仅移除其中非最后一个的Work元素:
<xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <!-- 仅删除每个Change下不是最后一个的Work元素 --> <xsl:template match="EmployeeInfo/Employee/Change/Work[not(position() = last())]"/>
问题原因分析
你原来的XSLT存在两个致命问题:
- 错误丢弃了Change节点本身:匹配
Change的模板没有复制Change节点及其属性,也没有处理除Work[last()]之外的其他子节点(比如StatusReport、Compensation),导致整个Change节点被完全替换,最终从输出中消失。 - 错误删除了所有Work元素:单独匹配
Change/Work并空处理的模板,会先把所有Work都删掉,后续即使想保留最后一个Work也没有节点可处理了。
输入与期望输出对照
输入XML
<?xml version='1.0' encoding='UTF-8'?> <EmployeeInfo> <Summary> <Event>1234</Event> <Version>1</Version> </Summary> <Employee> <EmployeeSummary> <ID>1234</ID> </EmployeeSummary> <Change updates="1"> <StatusReport> <Status>Active</Status> </StatusReport> <Work updates="1"> <Job>1</Job> </Work> <Work> <Job>1</Job> </Work> <Work updates="0"> <Job>1</Job> </Work> <Work updates="1"> <Job>2</Job> </Work> <Compensation> <Salary>Monthly</Salary> </Compensation> </Change> <Change updates="2"> <StatusReport> <Status>Active</Status> </StatusReport> <Info> <Email>sample@gmail.com</Email> </Info> <Work updates="1"> <Job>3</Job> </Work> <Work> <Job>3</Job> </Work> <Work updates="1"> <Job>4</Job> </Work> <Work updates="0"> <Job>4</Job> </Work> </Change> </Employee> </EmployeeInfo>
期望输出XML
<?xml version='1.0' encoding='UTF-8'?> <EmployeeInfo> <Summary> <Event>1234</Event> <Version>1</Version> </Summary> <Employee> <EmployeeSummary> <ID>1234</ID> </EmployeeSummary> <Change updates="1"> <StatusReport> <Status>Active</Status> </StatusReport> <Work updates="1"> <Job>2</Job> </Work> <Compensation> <Salary>Monthly</Salary> </Compensation> </Change> <Change updates="2"> <StatusReport> <Status>Active</Status> </StatusReport> <Info> <Email>sample@gmail.com</Email> </Info> <Work updates="0"> <Job>4</Job> </Work> </Change> </Employee> </EmployeeInfo>
内容的提问来源于stack exchange,提问作者Minako
相关产品推荐
相关产品推荐

