Это будет работать при условии, что каждая строка имеет одинаковое количество атрибутов:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" />
<xsl:template match="/root">
<table>
<tbody>
<tr>
<xsl:apply-templates select="row[1]" mode="header"/>
</tr>
<xsl:apply-templates select="row" mode="rows"/>
</tbody>
</table>
</xsl:template>
<xsl:template match="row" mode="header">
<xsl:for-each select="attribute::*">
<th><xsl:value-of select="local-name(.)" /></th>
</xsl:for-each>
</xsl:template>
<xsl:template match="row" mode="rows">
<tr>
<xsl:for-each select="attribute::*">
<td><xsl:value-of select="." /></td>
</xsl:for-each>
</tr>
</xsl:template>
</xsl:stylesheet>
Если могут быть дополнительные атрибуты, которые не представляют значения столбцов, вам необходимо отфильтровать их, проверив имя или что-то в этом роде.