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