Bryce Solis
Bryce Solis

Reputation: 3

Is there a function/way to transpose table rows and columns/?

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:

Simple Table

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

Answers (1)

michael.hor257k
michael.hor257k

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:

enter image description here


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

Related Questions