如何修改XSLT实现XML转TXT时保留原有节点顺序
问题根因
你当前使用的按节点类型分组遍历的写法,本质是人为指定了不同类型节点的输出优先级:比如先遍历所有元素节点、再遍历所有文本节点、最后遍历注释/处理指令节点,完全跳过了不同类型节点在原XML中混排的顺序逻辑,必然会打乱原有排列顺序。
调整方案
XSLT原生默认的节点遍历顺序就是XML文档的原始顺序,只要你不对节点做类型拆分选择、不手动加排序规则,就可以自动保留原顺序,调整步骤如下:
- 替换所有分类型选择节点的逻辑
把代码中类似如下的分组遍历代码全部删除:
统一替换为选中当前节点下所有子节点的通用写法,不区分节点类型:<!-- 错误写法:按节点类型拆分选择,强制分批次输出 --> <xsl:apply-templates select="*"/> <xsl:apply-templates select="text()"/> <xsl:apply-templates select="comment()"/><!-- 正确写法:按文档原始顺序选中所有子节点 --> <xsl:apply-templates select="node()"/> - 按需为不同类型的节点编写匹配模板
不需要在模板调用处控制顺序,XSLT会自动按节点的原始出现顺序,匹配对应的模板输出内容。通用基础模板参考如下:<!-- 配置纯文本输出,避免处理器自动格式化打乱内容 --> <xsl:output method="text" encoding="UTF-8" indent="no"/> <!-- 根节点匹配,启动处理流程 --> <xsl:template match="/"> <xsl:apply-templates select="node()"/> </xsl:template> <!-- 元素节点匹配:可根据你的输出需求自定义格式,比如加标识、缩进等 --> <xsl:template match="*"> <!-- 示例逻辑:输出元素标记,你可以替换为自己需要的格式规则 --> <xsl:text>ELEMENT: </xsl:text> <xsl:value-of select="name()"/> <xsl:text>
</xsl:text> <!-- 递归处理当前元素下的所有子节点,保持原顺序 --> <xsl:apply-templates select="node()"/> </xsl:template> <!-- 文本节点匹配:可过滤掉标签间用于排版的无意义空白 --> <xsl:template match="text()"> <xsl:if test="normalize-space(.) != ''"> <xsl:text>TEXT: </xsl:text> <xsl:value-of select="normalize-space(.)"/> <xsl:text>
</xsl:text> </xsl:if> </xsl:template> <!-- 注释节点匹配:如果不需要输出注释可以删除该模板 --> <xsl:template match="comment()"> <xsl:text>COMMENT: </xsl:text> <xsl:value-of select="."/> <xsl:text>
</xsl:text> </xsl:template> - 不要额外添加
xsl:sort逻辑,所有节点遍历都使用select="node()"的通用选择方式,即可完全保留原XML的节点排列顺序。
注意事项
如果你需要保留原XML中节点间的原始空白(比如缩进、换行),可以去掉文本节点模板里的
normalize-space()处理,直接输出.即可;如果不需要保留排版空白,保留normalize-space()过滤即可。
内容的提问来源于stack exchange,提问作者dinbo93
相关产品推荐
相关产品推荐

