我是XSLT的新手。我知道我需要为每个组使用xsl:for,但除了基本列表之外,我什么都想不出来。某种递归会更好地工作吗?任何XSLT1.0或2.0解决方案都可以。
下面是示例XML。请注意,将数据组织到树结构中最重要的属性是@taxonomy。其他属性@taxonomyName和@level作为可选的辅助属性提供。
<?xml version="1.0" encoding="utf-8"?>
<documents>
<document level="0" title="Root document test" taxonomy="" taxonomyName="" />
<document level="1" title="Level one document test" taxonomy="CategoryI" taxonomyName="CategoryI" />
<document level="1" title="Level one document test #2" taxonomy="CategoryII" taxonomyName="CategoryII" />
<document level="2" title="Level two document test" taxonomy="CategoryIISubcategoryA" taxonomyName="SubcategoryA" />
<document level="2" title="Level two document test #2" taxonomy="CategoryIISubcategoryA" taxonomyName="SubcategoryA" />
<document level="3" title="Level three document test" taxonomy="CategoryIISubcategoryAMicrocategory1" taxonomyName="Microcategory1" />
<document level="2" title="Level two, no level one test" taxonomy="CategoryIIISubcategoryZ" taxonomyName="SubcategoryZ" />
</documents>
以下是预期输出。(请注意,在输出中不需要缩进。我在这里这样做是为了可读性。)
<ul>
<li>Root document test</li>
<li>CategoryI
<ul>
<li>Level one document test</li>
</ul>
</li>
<li>CategoryII
<ul>
<li>Level one document test #2</li>
<li>SubcategoryA
<ul>
<li>Level two document test</li>
<li>Level two document test #2</li>
<li>Microcategory1
<ul>
<li>Level three document test</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>CategoryIII
<ul>
<li>SubcategoryZ
<ul>
<li>Level two, no subcategory test</li>
</ul>
</li>
</ul>
</li>
</ul>
这是我能做的最好的。
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:key name="contacts-by-taxonomy" match="document" use="@taxonomy" />
<xsl:template match="documents">
<ul>
<xsl:for-each-group select="document" group-by="@taxonomy">
<xsl:sort select="@taxonomy" />
<li>
<h3><xsl:value-of select="current-grouping-key()"/></h3>
<ul>
<xsl:for-each select="current-group()">
<li><xsl:value-of select="@title"/></li>
</xsl:for-each>
</ul>
</li>
</xsl:for-each-group>
</ul>
</xsl:template>
</xsl:stylesheet>
我会一直努力,但如果有人能给我一件救生衣,我将永远感激。谢谢
好吧,这终于是我的解决方案了。:-)基本上,它在树中递归,在每个级别,它通过="@taxonomy的下一个级别"为每个组执行一个。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" indent="yes" />
<xsl:template match="documents">
<ul>
<xsl:call-template name="tree-depth-n">
<xsl:with-param name="population" select="document"/>
<xsl:with-param name="depth" select="0"/>
<xsl:with-param name="taxonomy-so-far" select="''"/>
</xsl:call-template>
</ul>
</xsl:template>
<!-- This template is called with a population that are all descendants
of the same ancestors up to level n. -->
<xsl:template name="tree-depth-n">
<xsl:param name="depth" required="yes"/>
<xsl:param name="population" required="yes"/>
<xsl:param name="taxonomy-so-far" required="yes"/>
<!-- output a <li> for each document that is a leaf at this level,
and a <li> for each sub-taxon of this level. -->
<xsl:for-each-group select="$population"
group-by="string(tokenize(@taxonomy, '\')[$depth + 2])">
<xsl:sort select="@taxonomy" />
<xsl:choose>
<!-- process documents at this level. -->
<xsl:when test="current-grouping-key() = ''">
<xsl:for-each select="current-group()">
<li><xsl:value-of select="@title"/></li>
</xsl:for-each>
</xsl:when>
<!-- process subcategories -->
<xsl:otherwise>
<li>
<h3><xsl:value-of select="current-grouping-key()"/></h3>
<ul>
<!-- recurse -->
<xsl:call-template name="tree-depth-n">
<xsl:with-param name="population" select="current-group()"/>
<xsl:with-param name="depth" select="$depth + 1"/>
<xsl:with-param name="taxonomy-so-far"
select="concat($taxonomy-so-far, '\', current-grouping-key())"/>
</xsl:call-template>
</ul>
</li>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
对于给定的输入,输出为:
<ul>
<li>Root document test</li>
<li>
<h3>CategoryI</h3>
<ul>
<li>Level one document test</li>
</ul>
</li>
<li>
<h3>CategoryII</h3>
<ul>
<li>Level one document test #2</li>
<li>
<h3>SubcategoryA</h3>
<ul>
<li>Level two document test</li>
<li>Level two document test #2</li>
<li>
<h3>Microcategory1</h3>
<ul>
<li>Level three document test</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>
<h3>CategoryIII</h3>
<ul>
<li>
<h3>SubcategoryZ</h3>
<ul>
<li>Level two, no level one test</li>
</ul>
</li>
</ul>
</li>
</ul>
我相信这正是你想要的。(我把<h3>
放在那里,就像您在XSL尝试中一样,用于类别名称,而不是文档标题。)