Xslt 如何将Xml转换为分层Xml

Xslt 如何将Xml转换为分层Xml,xslt,xslt-2.0,Xslt,Xslt 2.0,我有这个XML文件,希望执行XSLT2.0转换 问题是,这些节点处于同一级别,并使用ID相互引用,例如: <?xml version="1.0" encoding="UTF-8"?> <Data id = "1" referenceID = "2 3"> Text1 </Data> <Data id = "2" referenceID = "4"> Text2 </Data> <Data id = "3" r

我有这个XML文件,希望执行XSLT2.0转换

问题是,这些节点处于同一级别,并使用ID相互引用,例如:

<?xml version="1.0" encoding="UTF-8"?>

<Data id = "1" referenceID = "2 3">
    Text1
</Data>

<Data id = "2" referenceID = "4">
    Text2
</Data>

<Data id = "3" referenceID = "5">
    Text3
</Data>

<Data id = "4">
    Text4
</Data>

<Data id = "5">
    Text5
</Data>

文本1
文本2
文本3
文本4
文本5
所需的输出应如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Level1>
    Text1
    <Level2>
        Text2
        <Level3>
            Text4
        </Level3>
    </Level2>

    <Level2>
        Text3
        <Level3>
            Text5
        </Level3>
    </Level2>
</Level1>

文本1
文本2
文本4
文本3
文本5
我已经尝试使用模板并递归调用它们,但没有成功。 也许有一个简单的方法来解决这类问题。
提前感谢您的帮助

您可以使用键通过
id
属性标识
数据
元素,然后使用
标记(@referenceID,'\s+')上的
key
函数遵循引用:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="3.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:key name="ref" match="Data" use="@id"/>

  <xsl:template match="*[Data[@id]]">
      <xsl:apply-templates select="key('ref', '1')"/>
  </xsl:template>

  <xsl:template match="Data">
      <xsl:param name="level" as="xs:integer" select="1"/>
      <xsl:element name="Level{$level}">
          <xsl:apply-templates select="node(), key('ref', tokenize(@referenceID, '\s+'))">
              <xsl:with-param name="level" select="$level + 1"/>
          </xsl:apply-templates>
      </xsl:element>
  </xsl:template>

</xsl:stylesheet>


这就提供了正确的结构,很难识别混合内容。

是否应该为
数据
元素提供一个公共容器元素?是什么决定了哪些元素构成了嵌套输出的第一级,这仅仅是顺序,还是您需要检查哪些元素没有被其他元素引用?谢谢您的输入!对不起,描述不准确。我已经给出,顶级ID是“1”,所有引用的ID都是这个ID的子级。因此必须遵循所有参考ID。数据元素有一个通用的容器,但我看不出这个容器如何帮助我进行转换。谢谢你的帮助!如果起始ID不是“1”或类似字符串“id2”的起始ID,这种方法是否也有效?例如,如果ID的引用类似于“id2”引用“id5”和“id5”引用“id11”,则该键与输入XML中用作
ID
属性的任何值一起工作。当然,您需要更改
以使用您拥有的任何值,例如
。如果需要将其作为参数,可以声明一个全局(顶级)
,然后将行更改为
。然后,在运行转换时可以设置全局参数(例如,从命令行或使用API或IDE)。谢谢Martin!我将您的建议用于全局变量,并且能够实现所需的输出!缩进通过使用: