是的,我知道一些答案,例如Flat to Nested structure based on attribute value using XSLT,但对我来说有重要的区别。
给出以下扁平XML结构。级别信息可能包含空白。包含级别信息的元素之间可以有任意数量的元素没有级别信息。应该使用级别规范将这些元素分配给上一个元素。
<doc>
<item>
<meta>
<text>abc</text>
</meta>
</item>
<item>
<meta>
<para>
<level>1</level>
<title>a</title>
</para>
</meta>
</item>
<item>
<meta>
<para>
<level>2</level>
<title>b</title>
</para>
</meta>
</item>
<item>
<meta>
<para>
<level>1</level>
<title>c</title>
</para>
</meta>
</item>
<item>
<meta>
<para>
<level>2</level>
<title>d</title>
</para>
</meta>
</item>
<item>
<meta>
<para>
<level>2</level>
<title>e</title>
</para>
</meta>
</item>
<item>
<meta>
<para>
<level>4</level>
<title>f</title>
</para>
</meta>
</item>
<item>
<meta>
<para>
<level>1</level>
<title>g</title>
</para>
</meta>
</item>
<item>
<meta>
<text>def</text>
</meta>
</item>
<item>
<meta>
<text>ghi</text>
</meta>
</item>
<item>
<meta>
<para>
<level>2</level>
<title>h</title>
</para>
</meta>
</item>
</doc>
转换后的结果应如下所示……
<text>abc</text>
<test title="a">
<test title="b"/>
</test>
<test para="c">
<test title="d"/>
<test title="e">
<test para="f"/>
</test>
</test>
<test title="g">
<text>def</text>
<text>ghi</text>
<test title="h"/>
</test>
我的转换方法如下。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="child" match="item"
use="generate-id(preceding-sibling::item[(meta/para/level) <= ((current()/meta/para/level) - 1)][1])"/>
<xsl:template match="/doc">
<xsl:apply-templates select="item[(meta/para/level) = 1]"/>
</xsl:template>
<xsl:template match="item">
<test title="{meta/para/title}">
<xsl:apply-templates select="key('child', generate-id())"/>
</test>
</xsl:template>
</xsl:stylesheet>
很遗憾,我找不到解决方法。
答案 0 :(得分:1)
怎么样:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="child1"
match="item[meta/para/level]"
use="generate-id(preceding-sibling::item[meta/para/level < current()/meta/para/level][1])"/>
<xsl:key name="child2"
match="item[meta/text]"
use="generate-id(preceding-sibling::item[meta/para/level][1])"/>
<xsl:template match="/doc">
<root>
<xsl:apply-templates select="item[meta/para/level = 1] | key('child2', '')"/>
</root>
</xsl:template>
<xsl:template match="item[meta/para/title]">
<test title="{meta/para/title}">
<xsl:apply-templates select="key('child1', generate-id()) | key('child2', generate-id())"/>
</test>
</xsl:template>
<xsl:template match="item[meta/text]">
<text>
<xsl:value-of select="meta/text"/>
</text>
</xsl:template>
</xsl:stylesheet>
我添加了root
元素以使结果成为格式正确的XML。