XML
  Home arrow XML arrow Page 4 - XSL Transformation With Xalan
Dev Shed Forums 
Administration  
AJAX  
Apache  
BrainDump  
DHTML  
Flash  
Java  
JavaScript  
Multimedia  
MySQL  
Oracle  
Perl  
PHP  
Practices  
Python  
Reviews  
Security  
Style-Sheets  
Web Services  
XML  
Zend  
Zope  
Forums Sitemap 
IBM® developerWorks 
Sun Developer Network 
Dedicated Servers 
E-Commerce Hosting 
Linux Web Hosting 
Managed Hosting 
Small Business Hosting 
Actuate Whitepapers 
Moblin 
VPS Hosting 
Weekly Newsletter

 
Developer Updates  
Free Website Content 
IBM developerWorks
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
XML

XSL Transformation With Xalan
By: icarus, (c) Melonfire
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 3 stars3 stars3 stars3 stars3 stars / 7
    2002-03-20

    Table of Contents:
  • XSL Transformation With Xalan
  • The Introductions
  • Meeting The World's Greatest Detective
  • The Anatomy Of A Transformation
  • The Write Stuff
  • Still Hungry?

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
    IBM developerWorks
     
    ADVERTISEMENT

    Be the architects of evolution and help create the mobile internet future. It’s your move---enter to win here!

    XSL Transformation With Xalan - The Anatomy Of A Transformation


    (Page 4 of 6 )

    As always with Java, the first step involves pulling all the required classes into the application.

    // import required classes import javax.xml.transform.*; import javax.xml.transform.stream.*; import java.io.*;
    In case you're wondering, first come the classes for JAXP, followed by the classes for exception handling and file I/O. Now, I bet you're wondering, what's JAXP? According to the Unofficial JAXP FAQ, available at http://xml.apache.org/~edwingo/jaxp-faq.html, the Java API for XML Processing (JAXP) "enables applications to parse and transform XML documents using an API that is independent of a particular XML processor implementation". Or, to put it very simply, JAXP provides an abstraction layer, or standard API, that allows for code reuse across different XSLT processors. You might be wondering how JAXP, as an abstraction layer, knows which class to use during the transformation process. This information is available via the javax.xml.transform.TransformerFactory property. In case this didn't make any sense to you, don't worry about it; if it did, and you want to know more, take a look at http://xml.apache.org/xalan-j/apidocs/javax/xml/transform/TransformerFactory.html Next, I've instantiated some variables to hold the names of the various files I'll be using in the application.

    // store the names of the files public static String xmlFile, xslFile, resultFile = "";
    And now for the constructor:

    // constructor public addressBookConverter(String xmlFile, String xslFile, String resultFile) { try { // create an instance of the TransformerFactory // this allows the developer to use an API that is independent of // a particular XML processor implementation. TransformerFactory tFactory = TransformerFactory.newInstance(); // create a transformer which takes the name of the stylesheet // as an input parameter Transformer transformer = tFactory.newTransformer(new StreamSource(xslFile)); // transform the given XML file transformer.transform(new StreamSource(xmlFile), new StreamResult(resultFile)); System.out.println("Done!"); } catch (TransformerException e) { System.err.println("The following error occured: " + e); } }
    The first step is to create an instance of the TransformerFactory class. This can be used to create a Transformer object, which reads the XSLT stylesheet and converts the templates within it into a Templates object. This Templates object is a dynamic representation of the instructions present in the XSLT file - you won't see any reference to it in the code above, because it all happens under the hood, but trust me, it exists.

    Once the stylesheet is processed, a new Transformer object is generated. This Transformer object does the hard work of applying the templates within the Templates object to the XML data to produce a new result tree, via its transform() method. The result tree is stored in the specified output file.

    Finally, the main() method sets the ball in motion:

    // everything starts here public static void main (String[] args) { if(args.length != 3) { System.err.println("Please specify three parameters:n1. The name and path to the XML file.n2. The name and path to the XSL file.n3. The name of the output file."); return; } // assign the parameters passed as input parameters to // the variables defined above xmlFile = args[0]; xslFile = args[1]; resultFile = args[2]; addressBookConverter myFirstExample = new addressBookConverter (xmlFile, xslFile, resultFile); }
    This method first checks to see if the correct number of arguments was passed. If so, it invokes the constructor to create an instance of the addressBookConverter class; if not, it displays an appropriate error message.{mospagebreak title=Six Degrees Of Separation} Let's move on to something a little more complicated. Let's suppose that I wanted to convert my address book from XML into a delimiter-separated ASCII file format, for easy import into another application. With XSLT and Xalan, the process is a snap.

    Here's the XML data:

    <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="/home/me/xsl/xml2csv.xsl"?> <addressbook> <item> <name>Bugs Bunny</name> <address>The Rabbit Hole, The Field behind Your House</address> <email>bugs@bunnyplanet.com</email> </item> <item> <name>Batman</name> <address>The Batcave, Gotham City</address> <tel>123 7654</tel> <url>http://www.belfry.net/</url> <email>bruce@gotham-millionaires.com</email> </item> </addressbook>
    Now, in order to convert this XML document into a delimiter-separated file, I need an XSLT stylesheet like this:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:strip-space elements="*"/> <!- Set the "|" symbol as the default delimiter à <xsl:param name="delimiter" select="normalize-space('|')"/> <xsl:template match="/addressbook"> <xsl:for-each select="item"> <xsl:value-of select="normalize-space(name)"/> <xsl:value-of select="$delimiter"/> <xsl:value-of select="normalize-space(address)"/> <xsl:value-of select="$delimiter"/> <xsl:value-of select="normalize-space(tel)"/> <xsl:value-of select="$delimiter"/> <xsl:value-of select="normalize-space(email)"/> <xsl:value-of select="$delimiter"/> <xsl:value-of select="normalize-space(url)"/> <!- hexadecimal value for the new-line character à <xsl:text>&#x0A;</xsl:text> </xsl:for-each> </xsl:template> </xsl:stylesheet>
    And here's the Java code to tie it all together:

    // imported java classes import javax.xml.transform.*; import javax.xml.transform.stream.*; import java.io.*; public class xml2csv { // store the names of the files public static String xmlFile, xslFile, resultFile,delimiterValue = ""; // parameters for the getAssociatedStylesheet() method of the TransformerFactory class // Set them to null as they are not essential here String media = null , title = null, charset = null; public xml2csv(String xmlFile, String resultFile, String delimiterValue) { try { // create an instance of the TransformerFactory class TransformerFactory tFactory = TransformerFactory.newInstance(); // get the name of the stylesheet that has been defined in the XML file. // create a Source object for use by the upcoming newTransformer() method Source stylesheet = tFactory.getAssociatedStylesheet (new StreamSource(xmlFile),media, title, charset); // create a transformer which takes the name of the stylesheet // as an input parameter Transformer transformer = tFactory.newTransformer(stylesheet); // set a delimiter via the setParameter() method of the transformer transformer.setParameter("delimiter",delimiterValue); // perform the transformation transformer.transform(new StreamSource(xmlFile), new StreamResult(resultFile)); System.out.println("Done!"); } catch (TransformerException e) { System.err.println("The following error occured: " + e); } } // everything starts here public static void main (String[] args) { if(args.length != 3) { System.err.println("Please specify three parameters:n1. The name and path to the XML file.n2. The name of the output file.n3. The delimiter to be used."); return; } // set some variables xmlFile = args[0]; resultFile = args[1]; delimiterValue = args[2]; xml2csv mySecondExample = new xml2csv(xmlFile, resultFile, delimiterValue); } }


    Most of the code is identical to the previous example. There are a couple of important differences, though. First, the parameters passed to the constructor are different in this case.

    public xml2csv(String xmlFile, String resultFile, String delimiterValue) { // snip }
    Over here, I'm passing three parameters to the constructor: the name of the XML file, the name of the output file, and the delimiter to be used between the various elements of a record. What about the XSLT file, you ask? Well, that's sourced automatically from the XML file via the getAssociatedStylesheet() method of the TransformerFactory class.

    // create an instance of the TransformerFactory class TransformerFactory tFactory = TransformerFactory.newInstance(); // get the name of the stylesheet that has been defined in the XML file. // create a Source object for use by the upcoming newTransformer() method Source stylesheet = tFactory.getAssociatedStylesheet (new StreamSource(xmlFile),media, title, charset); [/code]

    A new Source object is created to represent this stylesheet; this Source object is ultimately passed to the Transformer class.

    // create a transformer which takes the name of the stylesheet // as an input parameter Transformer transformer = tFactory.newTransformer(stylesheet);
    If you take a close look at the XSLT file above, you'll see that I'vedefined an XSLT parameter named "delimiter". This parameter isessentially a variable which can be accessed by XSLT, and a value can beassigned to it via the setParameter() method of the Transformer class.

    // set a delimiter via the setParameter() method of the transformer transformer.setParameter("delimiter",delimiterValue);
    In this case, the "delimiter" parameter is set to whatever delimiter wasspecified by the user.

    Finally, the actual transformation is performed, the output stored inthe desired output file, and a result code generated.[code]// perform the transformation transformer.transform(new StreamSource(xmlFile), newStreamResult(resultFile)); System.out.println("Done!");
    Here's what it looks like, assuming you use a pipe (|) as delimiter (I haven't used a comma simply because some of the entries already contain commas):

    Bugs Bunny|The Rabbit Hole, The Field behind Your House||bugs@bunnyplanet.com| Batman|The Batcave, Gotham City|123 7654|bruce@gotham-millionaires.com|http://www.belfry.net/
    Isn't it simple when you know how?

    More XML Articles
    More By icarus, (c) Melonfire


     

       

    XML ARTICLES

    - How to Set Up Podcasting and Vodcasting
    - Creating an RSS Reader Application
    - Building an RSS File
    - An Introduction to XUL Part 6
    - An Introduction to XUL Part 5
    - An Introduction to XUL Part 4
    - An Introduction to XUL Part 3
    - An Introduction to XUL Part 2
    - An Introduction to XUL Part 1
    - XML Matters: Practical XML Data Design and M...
    - Practical XML Data Design and Manipulation f...
    - SimpleXML
    - XForms Basics, Part 3
    - XForms Basics, Part 2
    - XForms Basics




    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 2 hosted by Hostway