Вот как я это сделаю, используя метод Мюнхена. Google '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, хотя он больше не доступен, на самом деле. Результат, который я получил:
<html>
<body>
<h1>file1</h1>
<p>desc1</p>
<p>desc2</p>
<h1>file2</h1>
<p>desc1</p>
</body>
</html>
Используется msxml4.
Я отсортировал вывод по файлу. Я не уверен, что ты этого хотел.
Надеюсь, это поможет.