Это решение не использует рекурсию и предлагает несколько полезных техник XSLT, таких как группировка по Мюнхену, ключи, поиск максимума и итерация без рекурсии.
Это преобразование :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kSectsByValue" match="SectionName"
use="."/>
<xsl:key name="kDocBySect" match="Document"
use="../SectionName"/>
<xsl:variable name="vCols" select=
"/*/*/SectionName
[generate-id()
=
generate-id(key('kSectsByValue',.)[1])
]"/>
<xsl:variable name="vMaxRows">
<xsl:for-each select="$vCols">
<xsl:sort data-type="number" order="descending"
select="count(key('kDocBySect', .))" />
<xsl:if test="position() = 1">
<xsl:value-of select="count(key('kDocBySect', .))"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/">
<table>
<tr>
<xsl:apply-templates select="$vCols"/>
</tr>
<xsl:for-each select=
"(/*/*/Document)[not(position() > $vMaxRows)]">
<tr>
<xsl:variable name="vPos" select="position()"/>
<xsl:for-each select="$vCols">
<td>
<xsl:value-of select=
"../Document[$vPos]/FileName"/>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template match="SectionName">
<td>
<xsl:value-of select="." />
</td>
</xsl:template>
</xsl:stylesheet>
при применении к исходному документу XML (исправлено, чтобы быть правильно сформированным):
<Documents>
<Section>
<SectionName>Green</SectionName>
<Document>
<FileName>Tier 1 Schedules</FileName>
</Document>
<Document>
<FileName>Tier 3 Schedules</FileName>
</Document>
<Document>
<FileName>Setback Schedule</FileName>
</Document>
<Document>
<FileName>Tier 2 Governance</FileName>
</Document>
</Section>
<Section>
<SectionName>MRO/Refurb</SectionName>
<Document>
<FileName>Tier 2 Governance</FileName>
</Document>
</Section>
</Documents>
дает желаемый результат :
<table>
<tr>
<td>Green</td>
<td>MRO/Refurb</td>
</tr>
<tr>
<td>Tier 1 Schedules</td>
<td>Tier 2 Governance</td>
</tr>
<tr>
<td>Tier 3 Schedules</td>
<td/>
</tr>
<tr>
<td>Setback Schedule</td>
<td/>
</tr>
<tr>
<td>Tier 2 Governance</td>
<td/>
</tr>
</table>
Примечание :
Мы используем мюнхенский метод для группировки , чтобы найти все разные имена столбцов, не полагаясь, что в документе XML они будут уникальными.
Ключи используются как для группировки мюнхенцев, так и для поиска всех элементов, принадлежащих столбцу.
Максимальное количество строк найдено и хранится в переменной $vMaxRows
Мы повторяем N раз , чтобы получить N строк таблицы - без использования рекурсии !
Строка N
выводится путем применения шаблонов ко всем элементам столбца , которые имеют позицию N
в своем столбце.