Вот полностью универсальное решение, которое работает с любым количеством столбцов :
<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="kColsByName" match="Std/*"
use="name()"/>
<xsl:variable name="vCols" select=
"*/*/*
[generate-id()
=
generate-id(key('kColsByName', name())[1])
]
"/>
<xsl:variable name="vNumCols" select="count($vCols)"/>
<xsl:template match="/*/Std">
<table>
<tr>
<xsl:apply-templates select="$vCols"
mode="head"/>
</tr>
<xsl:apply-templates select=
"*[position() mod $vNumCols = 1]"/>
</table>
</xsl:template>
<xsl:template match="Std/*" mode="head">
<th><xsl:value-of select="name()"/></th>
</xsl:template>
<xsl:template match="Std/*">
<tr>
<xsl:apply-templates mode="inrow" select=
"(. | following-sibling::*)
[not(position() > $vNumCols)]"/>
</tr>
</xsl:template>
<xsl:template match="Std/*" mode="inrow">
<td><xsl:value-of select="."/></td>
</xsl:template>
</xsl:stylesheet>
Когда это преобразование применяется к предоставленному документу XML :
<School>
<Std c="8">
<Name>ABC</Name>
<Age>12</Age>
<Name>EFG</Name>
<Age>11</Age>
<Name>PQR</Name>
<Age>12</Age>
<Name>XYZ</Name>
<Age>11</Age>
</Std>
</School>
желаемый, правильный результат получается :
<table>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
<tr>
<td>ABC</td>
<td>12</td>
</tr>
<tr>
<td>EFG</td>
<td>11</td>
</tr>
<tr>
<td>PQR</td>
<td>12</td>
</tr>
<tr>
<td>XYZ</td>
<td>11</td>
</tr>
</table>
Теперь, если мы добавим новый столбец, скажем Sex
, в исходный документ XML :
<School>
<Std c="8">
<Name>ABC</Name>
<Age>12</Age>
<Sex>M</Sex>
<Name>EFG</Name>
<Age>11</Age>
<Sex>F</Sex>
<Name>PQR</Name>
<Age>12</Age>
<Sex>F</Sex>
<Name>XYZ</Name>
<Age>11</Age>
<Sex>M</Sex>
</Std>
</School>
мы можем применить то же преобразование выше без каких-либо модификаций, и оно снова дает правильный результат - это показывает, что преобразование действительно универсально :
<table>
<tr>
<th>Name</th>
<th>Age</th>
<th>Sex</th>
</tr>
<tr>
<td>ABC</td>
<td>12</td>
<td>M</td>
</tr>
<tr>
<td>EFG</td>
<td>11</td>
<td>F</td>
</tr>
<tr>
<td>PQR</td>
<td>12</td>
<td>F</td>
</tr>
<tr>
<td>XYZ</td>
<td>11</td>
<td>M</td>
</tr>
</table>