Pete and I are very very smart.

February 23rd, 2004 | by Scott Jennings |

How many times has this happened to you? You have legacy data that’s been marked up to look like this:

Name ID Number Address Phone Number
Freddy McAwesome 123404 321 Fake St. 555-3454
Johnny Bigtime 478378 9728 Nonexistent St. 555-3893
Billy Badass 238989 3882 Keepdriving Ln. 555-9932

which is fine, I suppose, except it’s not very useful if you want to use that data in another application or share it with other webpages or render it using XSL. Data doesn’t belong in tables, it wants to be marked up descriptively, it wants to swim in XML. If that same data looked like this:

<root>
    <row rownum=”1″>
      <Name>Freddy McAwesome</Name>
      <ID_Number>123404</ID_Number>
      <Address>321 Fake St.</Address>
      <Phone_Number>555-3454</Phone_Number>

    </row>
    <row rownum=”2″>

      <Name>Johnny Bigtime</Name>
      <ID_Number>478378</ID_Number>
      <Address>9728 Nonexistent St.</Address>
      <Phone_Number>555-3893</Phone_Number>

    </row>
    <row rownum=”3″>

      <Name>Billy Badass</Name>
      <ID_Number>238989</ID_Number>
      <Address>3882 Keepdriving Ln.</Address>
      <Phone_Number>555-9932</Phone_Number>

    </row>

</root>

well then, you’d be in business. So today I decided I’d had enough with manually copying and pasting data from legacy tables into XML files, and started poking around for a way to automate it. So I poked and poked and failed, until I asked my brilliant coworker Pete O’Bryan to help me write an XSL stylesheet that transforms an HTML table to an XML file. This is what he came up with (and I helped and spruced a few things up):

<xsl:stylesheet xmlns:xsl=”http://www.w3.org/1999/XSL/Transform” version=”1.0″>
<xsl:output method=”xml” indent=”yes”/>
<xsl:template match=”/”>
    <root>
    <xsl:apply-templates select=”/table”/>
    </root>

</xsl:template>
<xsl:template match=”table”>

    <xsl:apply-templates select=”tr[position() > 1]” mode=”filler”/>

</xsl:template>
<xsl:template match=”tr” mode=”filler”>

    <xsl:variable name=”pos” select=”position()”/>
    <xsl:element name=”row”>
    <xsl:attribute name=”rownum”><xsl:value-of select=”position()” /></xsl:attribute>
    <xsl:apply-templates select=”td”/>
    </xsl:element>

</xsl:template>
<xsl:template match=”td”>

    <xsl:variable name=”pos” select=”position()”/>
    <xsl:apply-templates select=”/table/tr[1]/th[$pos]“>
    <xsl:with-param name=”filling” select=”.”/>
    </xsl:apply-templates>

</xsl:template>
<xsl:template match=”th”>

    <xsl:param name=”filling”/>
    <xsl:variable name=”cleanhead” select=”translate(translate(., ‘ ‘, ‘_’),’/',’_')”/>
    <xsl:element name=”{$cleanhead}”>
    <xsl:value-of select=”$filling”/>
    </xsl:element>

</xsl:template>
</xsl:stylesheet>

I searched the Web and couldn’t find anything like this, so Pete and I are happy to release this bit of code into the wild. XML and XSL are the future of the Internet, fools. Get on the wagon while you can.

Sorry, comments for this entry are closed at this time.