使用XSLT 1.0转换RNG文件生成嵌套树结构XML的实现问题
实现方案
你现有代码的核心问题是没有基于RNG的引用关系做递归遍历,而是直接遍历所有rng:define节点导致结构混乱。以下是可直接生成目标XML的XSLT实现:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:rng="http://relaxng.org/ns/structure/1.0"> <xsl:strip-space elements="*"/> <xsl:output indent="yes" method="xml" encoding="utf-8" omit-xml-declaration="yes"/> <!-- 核心key:通过name映射rng:define节点 --> <xsl:key name="define" match="rng:define" use="@name"/> <!-- 入口模板:从start节点的引用开始处理 --> <xsl:template match="/"> <xsl:apply-templates select="key('define', rng:grammar/rng:start/rng:ref/@name)"/> </xsl:template> <!-- 处理define节点:生成对应元素 --> <xsl:template match="rng:define"> <xsl:apply-templates select="rng:element"/> </xsl:template> <!-- 处理RNG元素定义:创建输出元素,递归处理子节点 --> <xsl:template match="rng:element"> <xsl:element name="{@name}"> <xsl:apply-templates/> </xsl:element> </xsl:template> <!-- 处理RNG引用:跳转至对应的define节点 --> <xsl:template match="rng:ref"> <xsl:apply-templates select="key('define', @name)"/> </xsl:template> <!-- 处理oneOrMore节点:直接处理子节点(示例仅输出一次符合需求) --> <xsl:template match="rng:oneOrMore"> <xsl:apply-templates/> </xsl:template> <!-- 处理值节点:直接输出文本内容 --> <xsl:template match="rng:value"> <xsl:value-of select="."/> </xsl:template> </xsl:stylesheet>
关键逻辑说明
- 首先声明了RNG的命名空间,保证XPath可以正确匹配RNG节点
- 定义通用
define键,所有rng:ref都可以通过@name快速找到对应的定义节点,天然支持递归嵌套 - 处理流程完全跟随RNG的引用关系:从start入口开始,遇到元素就创建对应节点,遇到引用就跳转至对应定义,遇到值就输出文本,自动生成嵌套结构
- 对
rng:oneOrMore做了简化处理,仅输出一次子节点,符合你给出的示例输出要求,如果需要生成多份可修改该模板逻辑。
内容的提问来源于stack exchange,提问作者Pick
相关产品推荐
相关产品推荐

