Reputation: 3
I am looking to transpose a table dynamically to be populated column-wise, rather than row-wise. My table headers must go column-wise first, and my subsequent data must populate it in that orientation.
I have created an example for simplicity.
My current table is as follows:
however, I would like it to look like:
First Name| Graham | Albert | Thomas
Last Name | Bell |Einstein| Edison
Nickname| Garry | Ally | Eddy
My XML is:
<?xml-stylesheet type = "text/xsl" href = "student.xsl"?>
<class>
<student>
<firstname>Graham</firstname>
<lastname>Bell</lastname>
<nickname>Garry</nickname>
</student>
<student>
<firstname>Albert</firstname>
<lastname>Einstein</lastname>
<nickname>Ally</nickname>
</student>
<student>
<firstname>Thomas</firstname>
<lastname>Edison</lastname>
<nickname>Eddy</nickname>
</student>
</class>
My XSL is:
<xsl:stylesheet version = "1.0"
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:template match = "/class">
<html>
<body>
<h2>Student List</h2>
<table border = "1">
<tr bgcolor="lightgreen">
<th>First Name</th>
<th>Last Name</th>
<th>Nick Name</th>
</tr>
<xsl:for-each select = "student">
<tr>
<td><xsl:value-of select = "firstname"/></td>
<td><xsl:value-of select = "lastname"/></td>
<td><xsl:value-of select = "nickname"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Thanks in advance!
Upvotes: 0
Views: 198
Reputation: 116982
For a generic transpose, you could do something like:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/class">
<table border="1">
<xsl:for-each select="student[1]/*">
<xsl:variable name="i" select="position()"/>
<tr>
<th>
<xsl:value-of select="name()"/>
</th>
<xsl:for-each select="../../student">
<td>
<xsl:value-of select="*[$i]"/>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
to get:
If you want to have your own labels, you will need to hard-code the table rows:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/class">
<table border="1">
<tr>
<th>First Name</th>
<xsl:for-each select="student">
<td>
<xsl:value-of select="firstname"/>
</td>
</xsl:for-each>
</tr>
<tr>
<th>Last Name</th>
<xsl:for-each select="student">
<td>
<xsl:value-of select="lastname"/>
</td>
</xsl:for-each>
</tr>
<tr>
<th>Nick Name</th>
<xsl:for-each select="student">
<td>
<xsl:value-of select="nickname"/>
</td>
</xsl:for-each>
</tr>
</table>
</xsl:template>
</xsl:stylesheet>
Alternatively, you could create a variable listing the row labels and loop over that to eliminate the code repetition:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="http://www.example.com/my"
exclude-result-prefixes="my">
<my:row-labels>
<label>First Name</label>
<label>Last Name</label>
<label>Nick Name</label>
</my:row-labels>
<xsl:template match="/class">
<xsl:variable name="student" select="student" />
<table border="1">
<xsl:for-each select="document('')/xsl:stylesheet/my:row-labels/label">
<xsl:variable name="i" select="position()"/>
<tr>
<th>
<xsl:value-of select="."/>
</th>
<xsl:for-each select="$student">
<td>
<xsl:value-of select="*[$i]"/>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1