从同级到嵌套元素的xslt

从同级到嵌套元素的xslt,xslt,Xslt,我是一名xslt初学者,我正在努力完成以下任务: 从这个xml(注意,我不知道父节点的子节点数): ... 我需要得到这个xml: <e1> <e2> <e3> <e4> ... </e4> </e3> </e2> </e1> ... 我试了好几次,但都没有得到正确的输出。这里有一个尝试: <xsl:template na

我是一名xslt初学者,我正在努力完成以下任务:

从这个xml(注意,我不知道父节点的子节点数):


...
我需要得到这个xml:

<e1>
  <e2>
    <e3>
      <e4>
        ...
      </e4>
    </e3>
  </e2>
</e1>

...
我试了好几次,但都没有得到正确的输出。这里有一个尝试:

<xsl:template name="test">
    <xsl:element name="{@id}">
        <xsl:if test="position() != last()">
            <xsl:call-template name="test"/>
        </xsl:if>
    </xsl:element>
</xsl:template>
<xsl:template match="parent">
    <parent>
        <xsl:for-each select="./*">
            <xsl:for-each select=".">
                <xsl:element name="{@id}">
                    <xsl:if test="position() != last()">
                        <xsl:call-template name="test"/>
                    </xsl:if>
                </xsl:element>
            </xsl:for-each>
        </xsl:for-each>
    </parent>
</xsl:template>

这里有一种方法:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="parent">
      <xsl:apply-templates select="*[1]"/>
    </xsl:template>

    <xsl:template match="parent/*">
      <xsl:element name="{@id}">
        <xsl:apply-templates select="following-sibling::*[1]"/>
      </xsl:element>
    </xsl:template>
</xsl:stylesheet>

显然,您需要添加一些对其他元素的特定处理,但希望这能为您指明正确结构的方向

它的工作原理是让父元素只处理它的第一个子元素,然后让父元素的每个子元素创建一个名称与
id
属性匹配的元素,然后递归地将下一个元素作为新的子元素处理


有一个问题需要解决-如果
id
属性包含的值不是有效的元素名称,转换将失败。

以下是一种方法:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="parent">
      <xsl:apply-templates select="*[1]"/>
    </xsl:template>

    <xsl:template match="parent/*">
      <xsl:element name="{@id}">
        <xsl:apply-templates select="following-sibling::*[1]"/>
      </xsl:element>
    </xsl:template>
</xsl:stylesheet>

显然,您需要添加一些对其他元素的特定处理,但希望这能为您指明正确结构的方向

它的工作原理是让父元素只处理它的第一个子元素,然后让父元素的每个子元素创建一个名称与
id
属性匹配的元素,然后递归地将下一个元素作为新的子元素处理


如果
id
属性包含的值不是有效的元素名称,转换将失败。

在XSLT 3中,有一种替代方法,它在递归函数中为每个组使用
,以尝试以允许使用处理器(如Saxon 9.8 EE)或其他版本的Saxon 9.8或Altova(不支持流式处理)进行流式处理的方式实现嵌套:



由于流式处理无法实现同级导航,我认为这是一种通过流式处理递归处理同级的方法。

在XSLT 3中有一种替代方法,它在递归函数中为每个组使用
,尝试以允许使用Saxon 9.8 EE或普通XSLT等处理器进行流式处理的方式实现嵌套3 Saxon 9.8其他版本或Altova(不支持流媒体)中的处理:



由于流媒体无法实现同级导航,我认为这是通过流媒体递归处理同级的一种方法。

即使这样做不对,您仍然可以在问题中包含您尝试过的XSLT吗?实际上,您可能离解决方案不远。非常感谢。您尝试的一个问题是,命名模板中的
指令实际上并没有更改当前元素,因此它将在同一元素上无限递归。即使它不正确,您仍然可以在问题中包含您尝试过的XSLT吗?实际上,您可能离解决方案不远。非常感谢。您尝试的一个问题是,命名模板中的
指令实际上并没有更改当前元素,因此它将在同一元素上无限递归。非常感谢!我现在明白了。作为参考,这种技术有时被称为“同级递归”:其思想是元素的模板规则将模板应用于紧随其后的同级,其匹配的模板规则则递归地执行相同的操作。非常感谢!我现在明白了。作为参考,这种技术有时被称为“同级递归”:其思想是,元素的模板规则将模板应用于紧随其后的同级,然后其匹配模板规则递归地执行相同的操作。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="#all"
    version="3.0">

    <xsl:mode on-no-match="shallow-copy" streamable="yes"/>

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

    <xsl:function name="mf:nest" as="node()*" streamability="absorbing">
        <xsl:param name="nodes" as="node()*"/>
        <xsl:for-each-group select="$nodes" group-adjacent="true()">
            <xsl:element name="{@id}">
                <xsl:sequence select="mf:nest(tail(current-group()))"/>
            </xsl:element>
        </xsl:for-each-group>
    </xsl:function>

    <xsl:template match="parent">
        <xsl:copy>
            <xsl:sequence select="mf:nest(*)"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>