使用XSLT按TSRFO_CONSIGNEE排序E1EDK33元素时出现重复问题
解决XSLT排序E1EDK33节点时出现重复的问题
你遇到的重复问题核心是XSLT默认模板的递归复制行为:如果你只写了输出排序后E1EDK33的逻辑,默认模板会自动复制所有未被显式匹配的节点,包括原有的E1EDK33,最终导致原节点和排序后的节点同时出现。
下面是两种可靠的解决思路,根据你的XML结构选择即可:
方案1:精准处理父节点,替换E1EDK33集合
这种方式通过匹配E1EDK33的父节点,先复制其他子节点,再输出排序后的E1EDK33,避免重复。
假设你的XML结构类似(根据实际结构调整父节点路径):
<ORDER> <OTHER_NODE>保留的其他节点</OTHER_NODE> <E1EDK33> <TSRFO_CONSIGNEE>B</TSRFO_CONSIGNEE> <INFO>数据B</INFO> </E1EDK33> <E1EDK33> <TSRFO_CONSIGNEE>A</TSRFO_CONSIGNEE> <INFO>数据A</INFO> </E1EDK33> </ORDER>
对应的XSLT代码:
<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> <!-- 匹配E1EDK33的父节点(这里是ORDER,替换成你实际的父节点) --> <xsl:template match="ORDER"> <xsl:copy> <!-- 先复制父节点下除E1EDK33外的所有子节点 --> <xsl:apply-templates select="*[not(local-name()='E1EDK33')]"/> <!-- 再输出排序后的E1EDK33节点 --> <xsl:apply-templates select="E1EDK33"> <xsl:sort select="TSRFO_CONSIGNEE" data-type="text" order="ascending"/> </xsl:apply-templates> </xsl:copy> </xsl:template> </xsl:stylesheet>
方案2:屏蔽原E1EDK33节点,再输出排序后的版本
通过空模板阻止默认模板复制原E1EDK33,再在父节点中单独输出排序后的集合:
<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> <!-- 空模板:阻止默认模板复制原E1EDK33节点 --> <xsl:template match="E1EDK33"/> <!-- 在父节点中输出排序后的E1EDK33 --> <xsl:template match="ORDER"> <xsl:copy> <xsl:apply-templates select="*[not(local-name()='E1EDK33')]"/> <xsl:for-each select="E1EDK33"> <xsl:sort select="TSRFO_CONSIGNEE"/> <xsl:copy-of select="."/> </xsl:for-each> </xsl:copy> </xsl:template> </xsl:stylesheet>
关键注意事项
- 必须确保父节点的匹配路径正确:比如你的E1EDK33可能嵌套在
<E1EDK01>或其他节点下,一定要替换成实际的父节点路径,否则逻辑不生效 - 不要单独只写一个输出排序E1EDK33的模板,这会和默认模板的复制行为冲突,导致重复
- 如果需要保留E1EDK33的子节点结构,
xsl:copy-of或基础复制模板都能保证子节点不丢失
内容的提问来源于stack exchange,提问作者JimHalpert
相关产品推荐
相关产品推荐

