在 XSLT1.0 中,您可以使用密钥来实现这一点。您通过子元素的第一个前面的父元素有效地对子元素进行分组,因此您可以定义以下键:
<xsl:key name="child" match="Child" use="generate-id(preceding-sibling::Parent[1])"/>
然后,在匹配父元素的模板中,您可以获得所有关联的子元素,如下所示:
<xsl:apply-templates select="key('child', generate-id())"/>
在这种情况下,这是完整的 XSLT。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="child" match="Child" use="generate-id(preceding-sibling::Parent[1])"/>
<xsl:template match="Family">
<Family>
<xsl:apply-templates select="Parent"/>
</Family>
</xsl:template>
<xsl:template match="Parent">
<Parent>
<ParentValue>
<xsl:value-of select="."/>
</ParentValue>
<xsl:apply-templates select="key('child', generate-id())"/>
</Parent>
</xsl:template>
<xsl:template match="Child">
<Child>
<ChildValue>
<xsl:value-of select="."/>
</ChildValue>
</Child>
</xsl:template>
</xsl:stylesheet>
当应用于您的 XML 时,将输出以下内容:
<Family>
<Parent>
<ParentValue>Parent1</ParentValue>
<Child>
<ChildValue>Child1</ChildValue>
</Child>
</Parent>
<Parent>
<ParentValue>Parent2</ParentValue>
<Child>
<ChildValue>Child1</ChildValue>
</Child>
<Child>
<ChildValue>Child2</ChildValue>
</Child>
</Parent>
<Parent>
<ParentValue>Parent3</ParentValue>
<Child>
<ChildValue>Child1</ChildValue>
</Child>
</Parent>
</Family>
在 XSLT2.0 中,您可以使用xsl:for-each-group。在您的情况下,您希望从Parent元素开始对元素进行分组。
<xsl:for-each-group select="*" group-starting-with="Parent">
然后选择子元素,你可以使用current-group函数:
<xsl:apply-templates select="current-group()[position() > 1]" />
这是 2.0 的完整 XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/Family">
<Family>
<xsl:for-each-group select="*" group-starting-with="Parent">
<Parent>
<ParentValue>
<xsl:value-of select="."/>
</ParentValue>
<xsl:apply-templates select="current-group()[position() > 1]" />
</Parent>
</xsl:for-each-group>
</Family>
</xsl:template>
<xsl:template match="Child">
<Child>
<ChildValue>
<xsl:value-of select="."/>
</ChildValue>
</Child>
</xsl:template>
</xsl:stylesheet>
这也应该输出相同的结果: