我是xslt的初学者,我真的在努力完成以下任务:
从此xml(注意,我不知道父节点的子节点数):
<parent>
<element_a id="e1"/>
<element_b id="e2"/>
<element_a id="e3"/>
<element_c id="e4"/>
...
</parent>
我需要获取此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>
答案 0 :(得分:1)
这是一种方法:
<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
属性包含的值不是有效的元素名称,则转换将失败。
答案 1 :(得分:0)
这里是XSLT 3中的替代方法,它在递归函数中使用for-each-group
来尝试实现嵌套,从而允许与Saxon 9.8 EE之类的处理器或Saxon 9.8其他版本中的常规XSLT 3处理进行流传输或在Altova(不支持流媒体)中:
<?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>
由于流式处理无法进行同级导航,我认为这是通过流式递归处理同级式的一种方法。