Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XML to HTML table with XSLT

Tags:

xslt

I need to be able to turn a flat xml data sets into html tables, and I'm having trouble finding syntax examples that will fit my need. I would like to use one stylesheet that can convert similar looking data sets into html tables with variable columns. This means it can't use any hard coded element names besides "rows" and "row".

The stylesheet I'm after would be able to convert:

<?xml version="1.0" encoding="UTF-8"?>
<rows>
  <row>
    <AccountId>BlPUAA0</AccountId>
    <AccountName>Initech</AccountName>
    <AcocuntStatus>Client</AcocuntStatus>
  </row>
  <row>
    <AccountId>CJxIAAW</AccountId>
    <AccountName>Intertrode</AccountName>
    <AcocuntStatus>Prospect</AcocuntStatus>
  </row>
</rows>

into:

<table>
  <tr>
    <th>AccountId</th>
    <th>AccountName</th>
    <th>AcocuntStatus</th>
  </tr>
  <tr>
    <td>BlPUAA0</td>
    <td>Initech</td>
    <td>Client</td>
  </tr>
  <tr>
    <td>CJxIAAW</td>
    <td>Intertrode</td>
    <td>Client</td>
  </tr>
</table>

and this:

<?xml version="1.0" encoding="UTF-8"?>
<rows>
  <row>
    <AccountId>BlPUAA0</AccountId>
    <AccountName>Initech</AccountName>
  </row>
  <row>
    <AccountId>CJxIAAW</AccountId>
    <AccountName>Intertrode</AccountName>
  </row>
</rows>

into this:

<table>
  <tr>
    <th>AccountId</th>
    <th>AccountName</th>
  </tr>
  <tr>
    <td>BlPUAA0</td>
    <td>Initech</td>
  </tr>
  <tr>
    <td>CJxIAAW</td>
    <td>Intertrode</td>
  </tr>
</table>
like image 243
tponthieux Avatar asked Apr 14 '11 01:04

tponthieux


People also ask

How do you display XML elements in an HTML table using XSLT?

Create an XSL stylesheet.xml version=”1.0″?> To bind the XML elements to a HTML table, the <for-each> XSL template must appear before each table row tag. This ensures that a new row is created for each <book> element. The <value-of> template will output the selected text of each child element into a separate table.

How can XSLT transform XML into HTML explain with example?

The standard way to transform XML data into other formats is by Extensible Stylesheet Language Transformations (XSLT). You can use the built-in XSLTRANSFORM function to convert XML documents into HTML, plain text, or different XML schemas. XSLT uses stylesheets to convert XML into other data formats.

How XML is converted into HTML format using XSLT?

Transform XML to HTMLWrite the Java class to transform the XML file data to HTML using XSLT file. We have put both XML and XSLT files under classpath and finaly transforms the XML data into HTML output. We write the output to the HTML file called books. html under the project's root directory.

How convert XML to XSLT?

Execute an XSLT transformation from an XML fileOpen an XML document in the XML editor. Associate an XSLT style sheet with the XML document. Add an xml-stylesheet processing instruction to the XML document. For example, add the following line to the document prolog: <?


4 Answers

A straight-forward and short solution:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*">
     <table><xsl:apply-templates select="row"/></table>
 </xsl:template>

 <xsl:template match="row[1]">
  <tr><xsl:apply-templates select="*" mode="header"/></tr>
  <xsl:call-template name="standardRow"/>
 </xsl:template>

 <xsl:template match="row" name="standardRow">
  <tr><xsl:apply-templates select="*"/></tr>
 </xsl:template>

 <xsl:template match="row/*">
  <td><xsl:apply-templates select="node()"/></td>
 </xsl:template>

 <xsl:template match="row/*" mode="header">
  <th><xsl:value-of select="name()"/></th>
 </xsl:template>
</xsl:stylesheet>

when applied on the first provided XML document:

<rows>
    <row>
        <AccountId>BlPUAA0</AccountId>
        <AccountName>Initech</AccountName>
        <AcocuntStatus>Client</AcocuntStatus>
    </row>
    <row>
        <AccountId>CJxIAAW</AccountId>
        <AccountName>Intertrode</AccountName>
        <AcocuntStatus>Prospect</AcocuntStatus>
    </row>
</rows>

the wanted, correct result is produced:

<table>
   <tr>
      <th>AccountId</th>
      <th>AccountName</th>
      <th>AcocuntStatus</th>
   </tr>
   <tr>
      <td>BlPUAA0</td>
      <td>Initech</td>
      <td>Client</td>
   </tr>
   <tr>
      <td>CJxIAAW</td>
      <td>Intertrode</td>
      <td>Prospect</td>
   </tr>
</table>

when applied on the second provided XML document:

<rows>
    <row>
        <AccountId>BlPUAA0</AccountId>
        <AccountName>Initech</AccountName>
    </row>
    <row>
        <AccountId>CJxIAAW</AccountId>
        <AccountName>Intertrode</AccountName>
    </row>
</rows>

again the desired, correct result is produced:

<table>
   <tr>
      <th>AccountId</th>
      <th>AccountName</th>
   </tr>
   <tr>
      <td>BlPUAA0</td>
      <td>Initech</td>
   </tr>
   <tr>
      <td>CJxIAAW</td>
      <td>Intertrode</td>
   </tr>
</table>
like image 171
Dimitre Novatchev Avatar answered Sep 21 '22 01:09

Dimitre Novatchev


I had the urge to try to solve this shortly after posting the question, and here is what I came up with. I guess it makes you wait 24 hours before you can answer it yourself.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:template match="/">
    <table>
      <tr>
        <xsl:for-each select="rows/row[1]/*">
          <th>
            <xsl:value-of select ="local-name()"/>
          </th>
        </xsl:for-each>
      </tr>
      <xsl:for-each select="rows/row">
        <tr>
          <xsl:for-each select="*">
            <td>
              <xsl:value-of select="."/>
            </td>
          </xsl:for-each>
        </tr>
      </xsl:for-each>
    </table>
  </xsl:template>
</xsl:stylesheet>
like image 40
tponthieux Avatar answered Sep 21 '22 01:09

tponthieux


This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <table>
            <xsl:apply-templates select="rows/row[1]" />
        </table>
    </xsl:template>
    <xsl:template match="row">
        <tr>
            <xsl:apply-templates mode="th" />
        </tr>
        <xsl:apply-templates select="../row" mode="td" />
    </xsl:template>
    <xsl:template match="row/*" mode="th">
        <th>
            <xsl:value-of select="local-name()" />
        </th>
    </xsl:template>
    <xsl:template match="row" mode="td">
        <tr>
            <xsl:apply-templates />
        </tr>
    </xsl:template>
    <xsl:template match="row/*">
        <td>
            <xsl:apply-templates />
        </td>
    </xsl:template>
</xsl:stylesheet>

Applied to:

<rows>
    <row>
        <AccountId>BlPUAA0</AccountId>
        <AccountName>Initech</AccountName>
        <AcocuntStatus>Client</AcocuntStatus>
    </row>
    <row>
        <AccountId>CJxIAAW</AccountId>
        <AccountName>Intertrode</AccountName>
        <AcocuntStatus>Prospect</AcocuntStatus>
    </row>
</rows>

Produces:

<table>
    <tr>
        <th>AccountId</th>
        <th>AccountName</th>
        <th>AcocuntStatus</th>
    </tr>
    <tr>
        <td>BlPUAA0</td>
        <td>Initech</td>
        <td>Client</td>
    </tr>
    <tr>
        <td>CJxIAAW</td>
        <td>Intertrode</td>
        <td>Prospect</td>
    </tr>
</table>

And applied to:

<rows>
  <row>
    <AccountId>BlPUAA0</AccountId>
    <AccountName>Initech</AccountName>
  </row>
  <row>
    <AccountId>CJxIAAW</AccountId>
    <AccountName>Intertrode</AccountName>
  </row>
</rows>

Produces:

<table>
    <tr>
        <th>AccountId</th>
        <th>AccountName</th>
    </tr>
    <tr>
        <td>BlPUAA0</td>
        <td>Initech</td>
    </tr>
    <tr>
        <td>CJxIAAW</td>
        <td>Intertrode</td>
    </tr>
</table>

Alternatively, this stylesheet produces the same output using a conditional and one fewer template:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <table>
            <xsl:apply-templates select="rows/row" />
        </table>
    </xsl:template>
    <xsl:template match="row">
        <xsl:if test="position()=1">
            <tr>
                <xsl:apply-templates mode="th" />
            </tr>
        </xsl:if>
        <tr>
            <xsl:apply-templates />
        </tr>
    </xsl:template>
    <xsl:template match="row/*" mode="th">
        <th>
            <xsl:value-of select="local-name()" />
        </th>
    </xsl:template>
    <xsl:template match="row/*">
        <td>
            <xsl:apply-templates />
        </td>
    </xsl:template>
</xsl:stylesheet>
like image 37
Wayne Avatar answered Sep 18 '22 01:09

Wayne


Few days ago I post an article, hope it can help you: http://web.swfideas.com/?p=12191

Asuming this data:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Edited by XMLSpy -->
<table-node>
  <tbody>
    <tr>
      <td>[C1R1]</td>
      <td>[C2R1]</td>
    </tr>
    <tr>
      <td>[C1R2]</td>
      <td>[C2R2]</td>
    </tr>
    <tr>
      <td>[C1R3]</td>
      <td>[C2R3]</td>
    </tr>
  </tbody>
</table-node>

Now, the core, our XSLT template:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Coded by SWFideas -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- table template -->
<xsl:template match="table-node">
    <table style="border:solid #000000 1px;border-spacing: 0;border-collapse: collapse;">
        <xsl:for-each select="tbody">
            <tbody>
                <xsl:for-each select="tr">
                    <tr>
                        <xsl:for-each select="td">
                            <td style="border:solid #000000 1px; padding: 5px;">
                                <xsl:value-of select="."/>
                            </td>
                        </xsl:for-each>                     
                    </tr>                 
                </xsl:for-each>
            </tbody>
        </xsl:for-each>
    <table>
</xsl:template>
</xsl:stylesheet>

In this first approach I’m avoiding to use COLSPAN and another real-life properties (implementation soon, I promise). So the result if we apply our XSLT will be like this:

<table style="border:solid #000000 1px;border-spacing: 0;border-collapse: collapse;">
    <tbody>
        <tr>
            <td style="border:solid #000000 1px; padding: 5px;">[C1R1]</td>
            <td style="border:solid #000000 1px; padding: 5px;">[C2R1]</td>
        </tr>
        <tr>
            <td style="border:solid #000000 1px; padding: 5px;">[C1R2]</td>
            <td style="border:solid #000000 1px; padding: 5px;">[C2R2]</td>
        </tr>
        <tr>
            <td style="border:solid #000000 1px; padding: 5px;">[C1R3]</td>
            <td style="border:solid #000000 1px; padding: 5px;">[C2R3]</td>
        </tr>
    </tbody>
</table>

You can try it here: http://www.xsltcake.com/slices/gNfh6i/2

like image 35
kcho0 Avatar answered Sep 22 '22 01:09

kcho0