如何使用XSLT 2.0实现两类XML场景的正确转换?
XML双场景转换解决方案(XSLT 2.0适配)
转换规则
- 场景1:当源XML中存在
ITEM2/SHL[KEY='S']时,直接原样输出所有内容,无需修改 - 场景2:当源XML中
SHL[KEY='S']直接位于Root下时,需将ITEM2/SHL[KEY='T']和对应编号的ITEM2/SHL[KEY='I']节点按T在前、I在后的顺序配对重排,其余节点保持原顺序
适配双场景的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> <!-- 针对Root节点的分支处理逻辑 --> <xsl:template match="Root"> <xsl:copy> <!-- 先输出所有非ITEM2的节点,保留原顺序 --> <xsl:apply-templates select="*[not(local-name()='ITEM2')]"/> <!-- 判断当前是否为场景1 --> <xsl:variable name="is-scenario1" select="boolean(ITEM2/SHL/KEY='S')"/> <!-- 场景1:直接输出所有ITEM2节点 --> <xsl:if test="$is-scenario1"> <xsl:apply-templates select="ITEM2"/> </xsl:if> <!-- 场景2:执行配对重排逻辑 --> <xsl:if test="not($is-scenario1)"> <!-- 先输出SHL[KEY='O']的ITEM2节点 --> <xsl:apply-templates select="ITEM2[SHL/KEY='O']"/> <!-- 按编号分组,将T和I节点配对输出 --> <xsl:for-each-group select="ITEM2[SHL/KEY=('T','I')]" group-by="(PO4/NUMBER, LIN/NUMBER)[.][1]"> <xsl:apply-templates select="current-group()[SHL/KEY='T']"/> <xsl:apply-templates select="current-group()[SHL/KEY='I']"/> </xsl:for-each-group> </xsl:if> </xsl:copy> </xsl:template> </xsl:stylesheet>
代码逻辑说明
- 身份模板:作为基础规则,保证所有节点在未被特殊处理时原样复制
- Root节点分支:
- 先处理
ITEM1、SHL、REF、SE等非ITEM2节点,保留原顺序 - 通过
is-scenario1变量判断场景:检查是否存在包含SHL[KEY='S']的ITEM2 - 场景1直接输出所有
ITEM2,不做调整 - 场景2中:
- 优先输出
SHL[KEY='O']的ITEM2节点,维持原位置 - 将
SHL[KEY='T']和SHL[KEY='I']的ITEM2按编号(PO4/NUMBER或LIN/NUMBER)分组,每组内先输出T节点,再输出对应I节点,实现配对重排
- 优先输出
- 先处理
内容的提问来源于stack exchange,提问作者AnirD
相关产品推荐
相关产品推荐

