tags:

views:

149

answers:

1

Hi,

I have developed an XSL file that transforms xml files into a html table. The idea is to have only one xsl file transform many xml files into a html table, instead of having 10 xml files with 10 accompanying xsl files. I've included the one xsl file and 2 xml files that uses the xsl file to transform them into a html tables. The problem I'm having is that I can't seem to figure out how the columns for the rows get created to complete the generated table. Please have test the code below to get an understanding. All support is welcome. Thanks!

tone

XSL File: test_xsl.xsl

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
<xsl:output method="html" indent="yes"/>

<xsl:template match="/root/sheet">
    <html>
        <head></head>
        <body>
            <table border="1" width="100%" cellpadding="0" cellspacing="0" height="100%">

                <xsl:apply-templates select="headers"/>

                <xsl:for-each select="rows">
                    <xsl:for-each select="item">
                        <tr>
                            <td>
                                <table border="1" width="100%" height="100%" cellpadding="0" cellspacing="0">
                                    <tr>
                                        <td>
                                            <b><xsl:value-of select="name" disable-output-escaping="yes" /></b>
                                        </td>

                                    </tr>
                                </table>
                            </td>
                        </tr>
                    </xsl:for-each>
                </xsl:for-each>
            </table>
        </body>
    </html>
</xsl:template>
<xsl:template match="headers">
    <tr>
        <xsl:apply-templates select="item"/>
    </tr>
</xsl:template>
<xsl:template match="headers//item">
    <th>
        <xsl:choose>
            <xsl:when test="item">
                <table border="1" width="100%" height="100%">
                    <tr><td colspan="{count(item)}"><xsl:value-of select="name"/></td></tr>
                    <xsl:apply-templates select="item"/>
                </table>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="name"/>
            </xsl:otherwise>
        </xsl:choose>
    </th>
</xsl:template>
</xsl:stylesheet>

XML File 1: test_xml1.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="test_xsl.xsl"?>

<root>
    <sheet>
        <titles>
            <item>
                <name><![CDATA[Title 1]]></name>
            </item>
            <item>
                <name><![CDATA[Title 2]]></name>
            </item>
            <item>
                <name><![CDATA[Title 3]]></name>
            </item>
        </titles>
        <headers>
            <item>
                <name><![CDATA[Header 1]]></name>
            </item>
            <item>
                <name><![CDATA[Header 2]]></name>
                <item>
                    <name><![CDATA[Sub header 1 of Header 2]]></name>
                </item>
                <item>
                    <name><![CDATA[Sub header 2 of Header 2]]></name>
                    <item>
                        <name><![CDATA[Sub header 1 of Sub header 2 of Header 2]]></name>
                    </item>
                    <item>
                        <name><![CDATA[Sub header 2 of Sub header 2 of Header 2]]></name>
                    </item>
                </item>
            </item>
            <item>
                <name><![CDATA[Header 3]]></name>
            </item>
        </headers>
        <rows>
            <item>
                <name><![CDATA[Row 1]]></name>
            </item>
            <item>
                <name><![CDATA[Row 2]]></name>
            </item>
            <item>
                <name><![CDATA[Row 3]]></name>
            </item>
            <item>
                <name><![CDATA[Row 4]]></name>
            </item>
        </rows>
    </sheet>
</root>

XML File 2: test_xml2.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="test_xsl.xsl"?>
<root>
<sheet>
  <titles>
   <item>
    <name><![CDATA[Title 1]]></name>
   </item>

   <item>
    <name><![CDATA[Title 2]]></name>
   </item>

   <item>
    <name><![CDATA[Title 3]]></name>
   </item>
  </titles>
  <headers>
    <item>
    <name><![CDATA[Header 1]]></name>
   </item>

   <item>
    <name><![CDATA[Header 2]]></name>
   </item>

   <item>
    <name><![CDATA[Header 3]]></name>
   </item>
   <item>
    <name><![CDATA[Header 4]]></name>

    <item>
     <name><![CDATA[Sub header 1 of Header 4]]></name>
    </item>

    <item>
     <name><![CDATA[Sub header 2 of Header 4]]></name>
    </item>
   </item>
  </headers>

  <rows>
   <item>
    <name><![CDATA[Row 1]]></name>
   </item>
   <item>
    <name><![CDATA[Row 2]]></name>
   </item>                           

   <item>
    <name><![CDATA[Row 3]]></name>
   </item>                           

   <item>
    <name><![CDATA[Row 4]]></name>
   </item>   


  </rows>
 </sheet>
</root>

UPDATE

Here is an xsl file that will format the test_xml1.xml file I've provided. When trying to use this xsl file with the test_xml2.xml file, you will notice that the table appears with a column missing. The reason for this is because it's being hard coded. Ideally this should be dynamic. Hope I was clear. Thanks for your help!

<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
<xsl:output method="html" indent="yes"/>

<xsl:template match="/root/sheet">
    <html>
        <head></head>
        <body>
            <table border="1" width="100%" cellpadding="0" cellspacing="0" height="100%">
                <xsl:apply-templates select="headers"/>
                <xsl:for-each select="rows">
                    <xsl:for-each select="item">
                        <tr>
                            <td>
                                <table border="1" width="100%" height="100%" cellpadding="0" cellspacing="0">
                                    <tr>
                                        <td>
                                            <b><xsl:value-of select="name" disable-output-escaping="yes" /></b>
                                        </td>

                                    </tr>
                                </table>
                            </td>
                            <td><br /></td>
                            <td><br /></td>
                        </tr>
                    </xsl:for-each>
                </xsl:for-each>
            </table>
        </body>
    </html>
</xsl:template>
<xsl:template match="headers">
    <tr>
        <xsl:apply-templates select="item"/>
    </tr>
</xsl:template>
<xsl:template match="headers//item">
    <th>
        <xsl:choose>
            <xsl:when test="item">
                <table border="1" width="100%" height="100%">
                    <tr><td colspan="{count(item)}" width="40%"><xsl:value-of select="name"/></td></tr>
                    <xsl:apply-templates select="item"/>
                </table>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="name"/>
            </xsl:otherwise>
        </xsl:choose>
    </th>
</xsl:template>

+1  A: 

There's no data for the columns and there's no relationship between the headers and the actual rows but this will produce the right number of (empty) cells...

<xsl:template match="/root/sheet">
    <html>
      <head></head>
      <body>
        <table border="1" width="100%" cellpadding="0" cellspacing="0" height="100%">
          <xsl:apply-templates select="headers"/>
          <xsl:for-each select="rows">
            <xsl:for-each select="item">
              <tr>
                <td>
                  <xsl:value-of select="name" disable-output-escaping="yes" />
                </td>
                <!--
                <td>
                  <br />
                </td>
                <td>
                  <br />
                </td>-->
                <!-- Loop through all the first level headers except the first one -->
                <xsl:for-each select="//headers/item[position() &gt; 1]">
                  <td>
                    <br />
                  </td>
                </xsl:for-each>
              </tr>
            </xsl:for-each>
          </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>

Basically, instead of hard coding the cells, you just loop though the first level headers to get the right number of cells. And in the sample code above, I'm skipping the first cell (position() > 1) as you are already outputing it.

Catch22
Thank you so much Catch22, you nailed it. Works Perfectly! Hey quick question if you don't mind. How can I make it so that the first header/column width is always 40%? And this doesn't seem to work properly in firefox, are u having that issue as well? Once again thanks, you came through at the 11th hour! tone
tonedigital
Hmmm - I just added the attribute: width="40%" to the first <td> and that worked fine in both IE }</style>
Catch22