Tuesday, 29 March 2011

XML to HTML through XSL

I think it was about 2005 or 2006 that we at Oracle had so-called Mudwrestle sessions. Colleagues organized workshops for each other on the latest technologies. We started at 14:00 and after some introduction we did some exercises to get familiar with the subject. Amongst subjects as Integration (InterConnect), java, linux, we had also XML. And there I got to know XSLT for the first time.

To get it "in the fingers", I thought it might be handy to have all my browser links in an xml file and have an xsl attached to have it transformed into html providing them in pop-lists and a button. With a little java script it is then possible to have the link loaded after choosing a link and pressing the button. So I created my first version of the XML and XSL. It was in the time that Internet Explorer 6 was pretty new or at least the current release. I think I was into Firefox already. IE6 and Firefox were able to load and process the xsl file when it was attached to the xml file. To do so you have to add the following tag to the top of your xml file:

<?xml-stylesheet href="links.xsl" type="text/xsl"?>

Like;
<?xml version="1.0"?>
<?xml-stylesheet href="links.xsl" type="text/xsl"?>
<link-lists
  name="Links"
  title="Internet Links"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Begin van de Lists!
  <lists>
    <list
      name="DarwinApps"
      title="Darwin Links">
      <link
        description="Darwin-IT"
        link="http://www.darwin-it.nl"
        name="Darwin-IT" />
...

The XSL that I created for it is given at the bottom of this post.
Last week I enhanced it a little to have a button to load all the links of a list at once. That is particularly handy for a list of webmail-urls to load at the start of your day.

I'm very fond of this xml/xsl combi. It is so simple, since it consist of three ascii files (xml, xsl and css). The xml file is easy to extend and after a reload in the browser the link-lists are renewed. The xsl is simple to enhance to add extra functionality. And the css makes it possible to have it a layout that complies with your taste or desktop. Skinning was never so easy. And it works in both Windows and Linux. And probably Mac OS. On Windows XP I even had it on my Active Desktop.  But I can't find how to do it on Windows 7 or Linux.

Later in history, also a few years ago (2009) I created a tool in java to edit the xml file. Also this one is enhanced a few times and last week I posted a blog on this tool. See here. I made it xml-parser-vendor-independent. And it's opensource thus you might take a look at the source.

To try the xml/xsl you can open the xml-links file from here. Of course you can download it to your laptop and edit it to add your own links and remove the ones not needed. The xsl is for download here and the css-file here. Place the xml and the xsl in the same folder, the css is expected in a subfolder called "style".

Below is the source of the XSL for investigation. As you can see I set it up in a modular way. I'm used to have a template for every hierarchical level of XML. And for particular functionalities, such as the generation of the java script for each poplist. You can use the xml-tool set in the the earlier post to perform a transform of the XML with the XSL to see the resulting HTML. Have fun with it.

<?xml version="1.0"?>
<!--  (c) 2008-2011, by Martien van den Akker  
Darwin-IT Professionals
-->

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output
    method="html" />  <!--  Variables  -->

  <xsl:variable
    name="newline">
    <xsl:text></xsl:text></xsl:variable>  <!--  main  -->

  <xsl:template
    match="/">
    <html>

      <xsl:call-template
        name="heading" />
      <body>
        <xsl:call-template
          name="body" /></body></html></xsl:template>
  <xsl:template
    name="heading">    <!--  Heading  -->

    <head>
      <title>Links</title>
      <LINK
        HREF="style/style.css"
        REL="STYLESHEET"
        TYPE="text/css" /></head>    <!--  Script to load a page  -->

    <script
      language="javascript">
      <xsl:text>function loadPage(link)
{
  newWdw=window.open(link,"_blank","");
}</xsl:text></script></xsl:template>
  <xsl:template
    name="body">    <!--  Body  -->

    <body>
      <xsl:apply-templates
        select="/link-lists" /></body></xsl:template>  <!--  /link-lists  -->

  <xsl:template
    match="link-lists"
    name="link-lists">

    <h1>
      <xsl:value-of
        select="@title" /></h1>
    <table>
      <xsl:apply-templates
        select="lists/list" /></table></xsl:template>  <!--  /link-lists/lists/list  -->

  <xsl:template
    match="lists/list"
    name="lists-list">
    <tr>
      <td>
        <xsl:value-of
          select="@title" /></td>      <!--  generate javascript for loading a link  -->

      <xsl:call-template
        name="loadLink" />      <!--  generate javascript for loading a links  -->

      <xsl:call-template
        name="loadAllLinks" />      <!--  generate a poplist and a button  -->

      <xsl:call-template
        name="writePopList" /></tr></xsl:template>  <!--  loadLink: generate a javascript that loads a link  -->

  <xsl:template
    name="loadLink">
    <xsl:text
      disable-output-escaping="yes">      <!--  script to load a link  -->

</xsl:text>
    <script
      language="javascript">
      <xsl:value-of
        select="concat($newline,'      function load', @name,'Link()')" />
      <xsl:text
        disable-output-escaping="yes">{</xsl:text>
      <xsl:value-of
        select="concat('        var l_idx = document.', @name, 'LinkSelector.select.selectedIndex;',$newline)" />
      <xsl:value-of
        select="concat('        var l_value = document.', @name, 'LinkSelector.select.options[l_idx].value;')" />
      <xsl:text
        disable-output-escaping="yes">if (l_value != "none")
        {
           loadPage(l_value);
        }
      }</xsl:text></script></xsl:template>  <!--  loadAllLinks: generate a javascript that loads all links of a poplist  -->

  <xsl:template
    name="loadAllLinks">
    <xsl:text
      disable-output-escaping="yes">      <!--  script to load a link  -->
</xsl:text> 
    <script
      language="javascript">
      <xsl:value-of
        select="concat($newline,'      function loadAll', @name,'Links()')" />
      <xsl:text
        disable-output-escaping="yes">{
        var l_idx;
        var l_value;</xsl:text>
      <xsl:value-of select="concat('        for(l_idx=0; l_idx&lt;document.', @name, 'LinkSelector.select.length; l_idx++)')"/>
   <xsl:value-of select="concat($newline,'        {',$newline)"/>
      <xsl:value-of select="concat('           l_value=document.', @name, 'LinkSelector.select.options[l_idx].value;')"/> 
      <xsl:text
        disable-output-escaping="yes">

    if (l_value != "none")
    {
            loadPage(l_value);
    }
        }
      }</xsl:text></script></xsl:template>
  <xsl:template
    name="writePopList">
    <td>
      <form
        name="{concat(@name, 'LinkSelector')}">
        <table
          border="0"
          cellspacing="0">
          <tr>
            <td
              width="250px">              <!-- Select  -->

              <select
                name="select">
                <option
                  value="none">Kies een link:</option>
                <xsl:for-each
                  select="link">
                  <option
                    value="{@link}">
                    <xsl:value-of
                      select="@name" /></option></xsl:for-each></select></td>
            <td>              <!--  Button  -->

              <input
                onclick="{concat('load',@name,'Link()')}"
                type="button"
                value="Toon" /></td>

            <td>              <!--  Button Load All -->

              <input
                onclick="{concat('loadAll',@name,'Links()')}"
                type="button"
                value="Toon alles" /></td></tr></table></form></td></xsl:template>
</xsl:stylesheet>

No comments :