XSL basics


I’ve been playing arround with XML and XSL transformations recently. XSL transformations may be very useful for:

  • transforming XML to XML with different structure.
  • converting XML to another well-known formats, as CSV or SQL. Then, you can pipe the output to another tools like awk/sqlplus or perform some complex querys in a RDBM.
  • simple ordering / extracting node-values from the XML. Do you want to extract only a numeric value from a SOAP-response, if there is no a “soap fault” element?

All the above possible usages make XSL a powerful tool to deal with XML specially when integrating applications.

So, lets see a sample XML file, storing some info about music CDs:

<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
    <cd>
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
<price>10.90</price>
        <year>1985</year>
    </cd>
    <cd>
        <title>Hide your heart</title>
        <artist>Bonnie Tyler</artist>
        <country>UK</country>
        <company>CBS Records</company>
<price>9.90</price>
        <year>1988</year>
    </cd>
....
</catalog>

And a Java class to perform XSL transformation:

public static void main(String[] args)
    throws FileNotFoundException,
    TransformerException {
    File inXMLFile = new File("input.xml");
    File inXSLFile = new File("transformation.xsl");
    File outXMLFile = new File("output.xml");

    javax.xml.transform.TransformerFactory tFactory =
    javax.xml.transform.TransformerFactory.newInstance();

    // Get the XML input document and the stylesheet
    javax.xml.transform.Source xmlSource =
    new javax.xml.transform.stream.StreamSource(inXMLFile);

    javax.xml.transform.Source xslSource =
    new javax.xml.transform.stream.StreamSource(inXSLFile);

    // Generate the transformer.
    javax.xml.transform.Transformer transformer =
    tFactory.newTransformer(xslSource);
    // Perform the transformation, sending the output to the response.
    transformer.transform(xmlSource,
    new javax.xml.transform.stream.StreamResult(outXMLFile));
}

In the code above, there are three files:

  • input.xml: XML input file. We are using the CD catalog as input for our tests.
  • transformation.xsl: XSL sheet. The cornerstone of this test.
  • output.xml: The resulting XML from the XSL processing will be stored here. The output may no be an XML file (csv,txt,…)

At this point, we have a Java class that can process an XML input file, using a XSL sheet. Lets move to the interesting part:

  1. Generating (X)HTML from XML input
  2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:template match="/">
     <html>
     <body>
    <h2>My CD Collection</h2>
    <table border="1">
    <tr bgcolor="#9acd32">
    <th align="left">Title</th>
    <th align="left">Artist</th>
    </tr>
    <xsl:for-each select="catalog/cd">
    <tr>
    <td><xsl:value-of select="title"/></td>
    <td><xsl:value-of select="artist"/></td>
    </tr>
    </xsl:for-each></table>
    </body>
     </html>
     </xsl:template>
     </xsl:stylesheet>

    Note the use of the namespace “xsl”. Processing the input file with this XSL sheet would yield the followin output:

    <html>
    <body>
    <h2>My CD Collection</h2>
    <table border="1">
    <tr bgcolor="#9acd32">
    <th align="left">Title</th>
    <th align="left">Artist</th>
    </tr>
    <tr>
    <td>Empire Burlesque</td>
    <td>Bob Dylan</td>
    </tr>
    <tr>
    <td>Hide your heart</td>
    <td>Bonnie Tyler</td>
    </tr>
    ....
    </html>
    
  3. Generate the same (X)HTML as above, but ordering by artist:
  4. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
    <html> <body>
    <table border="2" bgcolor="yellow">
    <tr>
    <th>Title</th>
    <th>Artist</th>
    </tr>
    <xsl:for-each select="catalog/cd">
     <xsl:sort select="artist"/>
    <tr>
    <td><xsl:value-of select="title"/></td>
    <td><xsl:value-of select="artist"/></td>
    </tr>
    </xsl:for-each></table>
    </body> </html>
    </xsl:template> </xsl:stylesheet>
    

    The output will be:

    <html>
    <body>
    <table bgcolor="yellow" border="2">
    <tr>
    <th>Title</th>
    <th>Artist</th>
    </tr>
    <tr>
    <td>Romanza</td>
    <td>Andrea Bocelli</td>
    </tr>
    <tr>
    <td>One night only</td>
    <td>Bee Gees</td>
    </tr>
    ...
    </html>
    
  5. Process a SOAP response and build an HTML file
  6. <?xml version="1.0"?>
    <soap:Envelope
    xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
    soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
      <soap:Body xmlns:m="http://www.example.org/stock">
        <m:GetStockPriceResponse>
          <m:Price>34.5</m:Price>
        </m:GetStockPriceResponse>
      </soap:Body>
    </soap:Envelope>
    

    XSL:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:m="http://www.example.org/stock">
    <xsl:template match="/">
    <html> <body>
    <table border="2" bgcolor="yellow">
    <tr>
    <th>Price</th>
    </tr>
    <xsl:for-each select="//m:GetStockPriceResponse">
    <tr>
    <td><xsl:value-of select="m:Price"/></td>
    </tr>
    </xsl:for-each></table>
    </body> </html>
    </xsl:template> </xsl:stylesheet>

    Output:

    <html xmlns:m="http://www.example.org/stock">
    <body>
    <table bgcolor="yellow" border="2">
    <tr>
    <th>Price</th>
    </tr>
    <tr>
    <td>34.5</td>
    </tr>
    </table>
    </body>
    </html>
  7. Process a SOAP response, but extracting only the interesting value
  8. With the same input as above, this XSL:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:m="http://www.example.org/stock">
     <xsl:output omit-xml-declaration="yes"/>
     <xsl:template match="/">
     <xsl:for-each select="//m:GetStockPriceResponse">
     <xsl:value-of select="m:Price"/>
     </xsl:for-each>
     </xsl:template>
     </xsl:stylesheet>
    

    Would output:

    34.5

    Note the declaration in the XSL of the “m” namespace used in the input and the “omit-

    xml-declaration” to avoid that the resulting output starts with “<¿xml …” 5.-Get a CSV from the CDcatalog XSL:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes"/>
     <xsl:template match="/">
     <xsl:for-each select="catalog/cd">
     <xsl:value-of select="title"/>|<xsl:value-of select="artist"/>|<xsl:value-of select="country"/>|<xsl:value-of select="price"/><xsl:text>&#xa;</xsl:text>
     </xsl:for-each>
     </xsl:template>
     </xsl:stylesheet>
    

    Outputs:

    Empire Burlesque|Bob Dylan|USA|10.90
    Hide your heart|Bonnie Tyler|UK|9.90
    Greatest Hits|Dolly Parton|USA|9.90
    Still got the blues|Gary Moore|UK|10.20
    Eros|Eros Ramazzotti|EU|9.90
    One night only|Bee Gees|UK|10.90
    ………

  1. Get a lot of insert statements to import the XML directly into a database
  2. XSL:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes"/>
     <xsl:template match="/">
     <xsl:for-each select="catalog/cd">insert into mycds (title,artist,country,price) values ("<xsl:value-of select="title"/>","<xsl:value-of select="artist"/>","<xsl:value-of select="country"/>",<xsl:value-of select="price"/>);
     </xsl:for-each>
     </xsl:template>
     </xsl:stylesheet>
    

    Output:

    insert into mycds (title,artist,country,price) values ("Empire Burlesque","Bob Dylan","USA",10.90);
     insert into mycds (title,artist,country,price) values ("Hide your heart","Bonnie Tyler","UK",9.90);
     insert into mycds (title,artist,country,price) values ("Greatest Hits","Dolly Parton","USA",9.90);
     insert into mycds (title,artist,country,price) values ("Still got the blues","Gary Moore","UK",10.20);
     insert into mycds (title,artist,country,price) values ("Eros","Eros Ramazzotti","EU",9.90);
     insert into mycds (title,artist,country,price) values ("One night only","Bee Gees","UK",10.90);
     ....
    

These are very basic examples mostly taken from w3schools but I found them useful for processing HL7/XML messages, and saved me lots of hours coding😉

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: