XSLT 1.0 实现XML节点固定排序及重复子节点输出
解决XML节点顺序固定及多<MAB.CAMS>节点输出问题
问题核心
现有系统生成的XML里,<SPR_CODE.SMO.CAMS>和<MOD_CODE.SMO.CAMS>的顺序在删除/更新操作时会颠倒,接收端要求结构顺序固定;同时当前XSLT 1.0无法正确输出数量可变(至少1个)的<MAB.CAMS>子节点,需要修正实现。
输入XML示例
<!-- 更新操作下的输入 --> <ROOT.SMO.CAMS> <MOD_CODE.SMO.CAMS>MOD001</MOD_CODE.SMO.CAMS> <SPR_CODE.SMO.CAMS>SPR001</SPR_CODE.SMO.CAMS> <MAB.CAMS> <MAB_FIELD1>VAL1</MAB_FIELD1> </MAB.CAMS> <MAB.CAMS> <MAB_FIELD1>VAL2</MAB_FIELD1> </MAB.CAMS> </ROOT.SMO.CAMS> <!-- 删除操作下的输入 --> <ROOT.SMO.CAMS> <SPR_CODE.SMO.CAMS>SPR002</SPR_CODE.SMO.CAMS> <MOD_CODE.SMO.CAMS>MOD002</MOD_CODE.SMO.CAMS> <MAB.CAMS> <MAB_FIELD1>VAL3</MAB_FIELD1> </MAB.CAMS> </ROOT.SMO.CAMS>
现有问题XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <ROOT.SMO.CAMS> <SPR_CODE.SMO.CAMS><xsl:value-of select="ROOT.SMO.CAMS/SPR_CODE.SMO.CAMS"/></SPR_CODE.SMO.CAMS> <MOD_CODE.SMO.CAMS><xsl:value-of select="ROOT.SMO.CAMS/MOD_CODE.SMO.CAMS"/></MOD_CODE.SMO.CAMS> <!-- 硬编码单个节点,无法处理多个<MAB.CAMS> --> <MAB.CAMS> <xsl:copy-of select="ROOT.SMO.CAMS/MAB.CAMS/*"/> </MAB.CAMS> </ROOT.SMO.CAMS> </xsl:template> </xsl:stylesheet>
期望输出XML
<!-- 对应更新操作的输出 --> <ROOT.SMO.CAMS> <SPR_CODE.SMO.CAMS>SPR001</SPR_CODE.SMO.CAMS> <MOD_CODE.SMO.CAMS>MOD001</MOD_CODE.SMO.CAMS> <MAB.CAMS> <MAB_FIELD1>VAL1</MAB_FIELD1> </MAB.CAMS> <MAB.CAMS> <MAB_FIELD1>VAL2</MAB_FIELD1> </MAB.CAMS> </ROOT.SMO.CAMS> <!-- 对应删除操作的输出 --> <ROOT.SMO.CAMS> <SPR_CODE.SMO.CAMS>SPR002</SPR_CODE.SMO.CAMS> <MOD_CODE.SMO.CAMS>MOD002</MOD_CODE.SMO.CAMS> <MAB.CAMS> <MAB_FIELD1>VAL3</MAB_FIELD1> </MAB.CAMS> </ROOT.SMO.CAMS>
修正后的XSLT 1.0实现
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 匹配根节点,构建固定顺序结构 --> <xsl:template match="/ROOT.SMO.CAMS"> <ROOT.SMO.CAMS> <!-- 强制先输出SPR_CODE节点,无视输入顺序 --> <xsl:copy-of select="SPR_CODE.SMO.CAMS"/> <!-- 再输出MOD_CODE节点 --> <xsl:copy-of select="MOD_CODE.SMO.CAMS"/> <!-- 遍历所有MAB.CAMS节点,逐个完整复制 --> <xsl:for-each select="MAB.CAMS"> <xsl:copy-of select="."/> </xsl:for-each> </ROOT.SMO.CAMS> </xsl:template> <!-- 兜底模板:原样复制未匹配的节点/属性,避免内容丢失(可选) --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
关键说明
- 固定节点顺序:通过直接指定
SPR_CODE.SMO.CAMS和MOD_CODE.SMO.CAMS的输出顺序,不管输入里的节点顺序如何,都会严格按照要求先输出SPR节点,再输出MOD节点。 - 处理多<MAB.CAMS>节点:使用
<xsl:for-each>遍历所有<MAB.CAMS>节点,配合<xsl:copy-of select="."/>完整复制每个节点及其子内容,无论节点数量多少都能正确输出。 - 兜底模板:如果XML中存在其他需要保留的节点或属性,兜底模板会原样复制,确保输出结构的完整性(不需要的话可以直接删除)。
内容的提问来源于stack exchange,提问作者jonah
相关产品推荐
相关产品推荐

