这就是我的做法,使用 Muenchean 方法。谷歌“xslt muenchean”从更聪明的人那里获得更多信息。可能有一个聪明的方法,但我会把它留给其他人。
请注意,我避免在 xml 元素名称的开头使用大写字母,例如“文件”,但这取决于您。
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:key name="files" match="/Problems/Problem/File" use="./text()"/>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates select="Problems"/>
</body>
</html>
</xsl:template>
<xsl:template match="Problems">
<xsl:for-each select="Problem/File[generate-id(.) = generate-id(key('files', .))]">
<xsl:sort select="."/>
<h1>
<xsl:value-of select="."/>
</h1>
<xsl:apply-templates select="../../Problem[File=current()/text()]"/>
</xsl:for-each>
</xsl:template>
<xsl:template match="Problem">
<p>
<xsl:value-of select="Description/text()"/>
</p>
</xsl:template>
</xsl:stylesheet>
这个想法是,使用它的文本值来键入每个 File 元素。然后仅显示与键控元素相同的文件值。要检查它们是否相同,请使用 generate-id。有一种类似的方法可以比较匹配的第一个元素。我不能告诉你哪个更有效。
我已经使用 Marrowsoft Xselerator 测试了这里的代码,这是我最喜欢的 xslt 工具,虽然不再可用,afaik。我得到的结果是:
<html>
<body>
<h1>file1</h1>
<p>desc1</p>
<p>desc2</p>
<h1>file2</h1>
<p>desc1</p>
</body>
</html>
这是使用 msxml4。
我已经按文件对输出进行了排序。我不确定你是否想要那个。
我希望这有帮助。