XML for the absolute beginner

A guided tour from HTML to processing XML with Java

1 2 3 Page 3
Page 3 of 3

XSL: I like your style

People who work in SGML and need to format it generally use DSSSL (Document Style Semantics and Specification Language) to do the job. DSSSL is a dialect of Scheme, itself a venerable and popular form of LISP (which stands either for "List Processing" or lots of irritating, superfluous parentheses," depending on who you ask). Of course, if you're using DSSSL, you're already an SGML god and veteran LISP hacker, and therefore should not be reading in this article.

Fortunately, the W3C committees discussing style, HTML, and XML have included in their design the Extensible Style Language, or XSL. XSL is based on DSSSL (and DSSSL-O, the online version of DSSSL), and also uses some of the style elements of CSS. It's simpler than DSSSL, while retaining much of its power (much like the relationship between XML and SGML). XSL's notation, however, may be surprising: it's XML. The simplest way to say it is: XSL is an XML document that specifies how to transform another XML document. Say, what?

Why XSL is so useful

XSL is immensely powerful. It can be used to add structure to a document (as in CSS), and it can also completely rearrange the input elements for a particular purpose. For example, XSL can transform XML of one structure into HTML of a different structure. (We'll see an example of this below.) XSL can also restructure XML into other document formats: TeX, RTF, and PostScript.

XSL can even transform XML into a different dialect of XML! This may sound crazy, but it's actually a pretty cool idea. For example, multiple presentations of the same information could be produced by several different XSL files applied to the same XML input. Or, let's say two systems speak different "dialects" of XML but have similar information requirements. XSL could be used to translate the output of the first system into something compatible with the input of the second system.

These last few reasons are of special interest to Java programmers, since XSL can be used to translate between different languages in a distributed network of subsystems, as well as to format documents. Understanding how to use XSL in simple applications, like transforming XML to HTML, will help a Java developer understand XSL in general. Let's look at an example of how to transform XML to HTML with an XSL style sheet.

Formatting XML as HTML: An example

An XSL file is a series of rules, called templates, that are applied to an input XML file. Each time a template matches something in the input, the template produces a new structure in the output (often HTML, as in the example we're about to see). The new structure is the XML's content, with the appropriate style applied and arranged as the XSL specifies. The templates in the XSL file are written in XML, using specific tags with defined meanings.

The example below refers again to the XML recipe example in Listing 3. We're going to look at an XSL file that transforms the XML in Listing 3 into the HTML in Listing 1.

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/Recipe">
    <HTML>
    <HEAD>
    <TITLE>
    <xsl:value-of select="Name"/>
    </TITLE>
    </HEAD>
    <BODY>
    <H3>
    <xsl:value-of select="Name"/>
    </H3>
    <STRONG>
    <xsl:value-of select="Description"/>
    </STRONG>
    <xsl:apply-templates/>
    </BODY>
    </HTML>
</xsl:template>
<!-- Format ingredients -->
<xsl:template match="Ingredients">
    <H4>Ingredients</H4>
    <TABLE BORDER="1">
    <TR BGCOLOR="#308030"><TH>Qty</TH><TH>Units</TH><TH>Item</TH></TR>
    <xsl:for-each select="Ingredient">
    <TR>
    <!-- handle empty Qty elements separately -->
    <xsl:if test='Qty[not(.="")]' > 
        <TD><xsl:value-of select="Qty"/></TD>
    </xsl:if>
    <xsl:if test='Qty[.=""]' > 
        <TD BGCOLOR="#404040"> </TD>
    </xsl:if>
    <TD><xsl:value-of select="Qty/@unit"/></TD>
    <TD><xsl:value-of select="Item"/>
    <xsl:if test='Item/@optional="1"'>
       <SPAN> -- <em><STRONG>optional</STRONG></em></SPAN>
    </xsl:if>
    </TD>
    </TR>
    </xsl:for-each>
    </TABLE>
</xsl:template>
<!-- Format instructions -->
<xsl:template match="Instructions">
    <H4>Instructions</H4>
    <OL>
    <xsl:apply-templates select="Step"/>
    </OL>
</xsl:template>
<xsl:template match="Step">
<LI><xsl:value-of select="."/></LI>
</xsl:template>
<!-- ignore all not matched -->
<xsl:template match="*" priority="-1"/>
</xsl:stylesheet>

Listing 7. XSL used as an XML language that transforms XML into something else

(A printable version of this file is in example.xsl).

Looking at this code you'll notice, first of all, that the file starts with the <?xml...?> tag, indicating that this file is XML (even though it's also XSL). Each template is bounded by the tags <xsl:template ...> and </xsl:template ...>. Every tag that begins with <xsl: is an XSL command.

While we won't go over all the templates in the XSL file (since this isn't an XSL tutorial), Listing 8 provides a quick look at the first template in the file, just to get the general idea.

<xsl:template match="/Recipe">
    <HTML>
    <HEAD>
    <TITLE>
    <xsl:value-of select="Name"/>
    </TITLE>
    </HEAD>
    <BODY>
    <H3>
    <xsl:value-of select="Name"/>
    </H3>
    <U>
    <xsl:value-of select="Description"/>
    </U>
    <xsl:apply-templates/>
    </BODY>
    </HTML>
</xsl:template>

Listing 8. The first template from the XSL style sheet in Listing 7

Notice the <xsl:template> tag: It has an attribute match="/Recipe". This indicates that this template is to be applied when a <Recipe> element is encountered at the input. Everything enclosed within this <xsl:template> element will be placed in the output.

The XSL processor sees a <Recipe> element, so it begins building its output by using the contents of the <xsl:template> element in the XSL file. It adds an <HTML> element, then a <HEAD> element inside of that, and then a <TITLE> element. It's actually building a new HTML document by creating HTML from the template, based on what it sees. The <xsl:value-of> tag instructs the XSL processor to go get the text contained in some other element -- in this case, the sub element <Name>. Moving a few lines down, you can see the same thing happening, as the XSL processor again fetches and uses the same string within the <H3> tag, and the <Description> tag after it. (Note that we're using the same text in more than one place in a document, something CSS simply can't do.) Finally, we come to the <xsl:apply-templates> command, which tells the XSL processor to apply all the other templates in the file to the input.

The resulting HTML is very similar to the HTML we saw in Listing 1. If you want to study the XML, XSL, and resulting HTML, and want to learn how to use XSL to format XML yourself, see the links on XSL in the Resources section of this article.

Additional XSL capabilities

XSL isn't limited to just producing HTML. XSL also has complete support for "native" formatting, which doesn't rely on translation to some other format. Nobody has yet implemented this part of XSL, though, primarily because page formatting and layout is a very tough to wrangle. (There is, however, a contest to implement all of XSL. See Resources.)

XSL's design also includes embedded scripting. Currently, IBM's LotusXSL package (written in Java) provides the functionality of almost all of the current draft specification of XSL, including the ability to call embedded ECMAScript (the European standard JavaScript) from XSL templates.

Of course, as always, with power comes complexity. Learning to write XSL isn't a piece of cake. But the power's there if you want it.

XML is more than just content management

XSL, like CSS, can be used on either the client or the server in a client/server system. This fact provides immense flexibility and organization to Web site designers and managers. So much so, in fact, that many people think of XML, CSS, and XSL as another set of technologies for "content management" for their Web sites. It makes styling Web documents easier and more consistent, facilitates version control of the site, simplifies multibrowser management (think of using a style sheet to overcome the many differences between browsers), and so forth. CSS is also useful for Dynamic HTML (which we'll discuss a bit below), where much of the user interaction occurs on the client side, where it belongs. From the point of view of people managing Web sites, XML, CSS, and XSL are indeed big wins. And yet, there's a whole world of applications that have nothing to do with browsers and Web pages. The map of that world is called the Document Object Model.

Modeling information structure in XML

So far, we've looked at XML as a way of representing data as human-readable documents, and we've spent some time discussing formatting. But XML's real power is in its ability to represent information structure -- how various pieces of information relate to one another -- in much the same way a database might.

Structured documents of the type we've been looking at have the property that all of their elements nest inside one another, as in Listing 5 above. Instead of looking at a document as a file, though, consider what happens if we look at the structure of the tags as a tree:

Figure 3. The recipe represented as a tree structure

The figure above shows the recipe as a tree of document tags. The child nodes of a document nest within the parent node. What if there were a way to automagically convert an XML document into a tree of objects in a programming language -- like, oh, say, Java maybe? And what if these objects all had properties that could be set and retrieved -- such as the list of each element's children, the text each object contained, and so on. Wouldn't that be interesting?

The Document Object Model (DOM) Level 1 Recommendation (see Resources), created by a W3C committee, describes a set of language-neutral interfaces capable of representing any well-formed XML or HTML document.

With the DOM, HTML and XML documents can be manipulated as objects, instead of just as streams of text. In fact, from the DOM point of view, the document is the object tree, and the XML, HTML, or what have you is simply a persistent representation of that tree.

The availability of the DOM makes it much simpler to read and write structured document files, since standard HTML and XML parsers are written to produce DOM trees. If these objects have GUI representations, it's easy to see how to create an application that reads structured document files (XML or HTML), lets the user edit the structure visually, and then save it in its original format. Programs that interface with existing Web sites become much easier to write, because once the document is parsed, you're working with objects native to your programming language.

One of the earliest popular uses for the Document Object Model is Dynamic HTML, where client-side scripts manipulate and display (and redisplay) an HTML document in response to user actions. Dynamic HTML manipulates the client-side document in terms of the scripting language's binding to the DOM structure of the document being displayed. For instance, a <BUTTON> object might, when clicked, reorder a table on the same page by sorting the <TR> (table row) nodes on a particular column.

But aside from all this browers-document-Web technology, the DOM provides a common way of accessing general data structures from structured documents. Any language that has a binding (that is, a specific set of interfaces that implement the DOM in that language) can use XML as an interface for storing, retrieving, and processing generic hierarchical (and even nonhierarchical) object structures.

How DOM and XML work together

The DOM opens the door to using XML as the lingua franca of data interchange on the Internet, and even within applications. Tim Berners-Lee, discussed earlier and commonly known as the "inventor of the World Wide Web," says that, these days, it's important to understand that if a system you're designing survives, it will someday be used as a module in another system. So it's best to design it that way from the start. The DOM is completely described in IDL, the Interface Definition Language used in CORBA, so it's connected to existing software interoperation standards.

Let's think a moment about how DOM with XML would be useful in programming a database system. First, represent your database schema as a set of DOM objects. Want a document that describes that schema? No problem: write it out as XML. Use XSL to format the XML as HTML and you've got a complete, browseable schema reference that's always up to date. Want to automatically construct SQL for updating your relational database from a record set coming into your system? Just traverse your database's (DOM) schema tree, matching up the names of the columns from the record set with those of the schema, and build an SQL UPDATE statement as you go. What's that you say? The schema has changed, and the record set you've received doesn't match up with the new schema? You can write code to handle that, or present the user with error messages that state exactly what's wrong. You even might be able to use XSL to refactor the DOM tree of your record set into something matching the new schema.

Finally, it's time to start programming in Java! In the next section, we're going to examine the Java bindings of the DOM and see how to use the DOM in a Java program.

XML and Java

Up to this point I've been laying out general information about XML, without a lot of reference to Java. Now that you understand XML, it's time to look at how to process XML in Java. Java's a great language for XML, as you'll see. It provides a portable data format that nicely complements Java's portable code.

SAX appeal

The easiest way to process an XML file in Java is by using the Simple API for XML, or SAX. SAX is a simple Java interface that many Java parsers can use. A SAX parser is a class that implements the interface org.xml.sax.Parser. This parser "walks" the tree of document nodes in an XML file, calling the methods of user-defined handler classes.

To process an XML document, the programmer creates a class that implements interface org.xml.sax.DocumentHandler. The Parser object (that is, the object that implements org.xml.sax.Parser) reads the XML from its input source, calling the methods of the DocumentHandler when tags, input strings, and so on are recognized at the input.

The methods of the DocumentHandler interface are as shown in Listing 9.

public interface DocumentHandler {

public abstract void setDocumentLocator (Locator locator);

public abstract void startDocument () throws SAXException;

public abstract void endDocument () throws SAXException;

public abstract void startElement (String name, AttributeList atts) throws SAXException;

public abstract void endElement (String name) throws SAXException;

public abstract void characters (char ch[], int start, int length) throws SAXException;

public abstract void ignorableWhitespace (char ch[], int start, int length) throws SAXException;

public abstract void processingInstruction (String target, String data) throws SAXException; }

Listing 9. interface org.xml.sax.DocumentHandler

Package org.xml.sax includes a utility class called HandlerBase, which implements the interface in Listing 9 (as well as some other interfaces in the SAX package) with methods that do nothing. Programmers can create a subclass of HandlerBase that overrides only the methods they want to use.

For example, say we want a class that counts the elements in an XML document. We could write a class as follows:

import org.xml.sax.*;
public class ElementCounter extends HandlerBase {
    protected int _iElements = 0;
    public ElementCounter() { }
    // Each time the SAX parser encounters an element, it
    // will call this method
    public void startElement (String name, AttributeList atts)
        throws SAXException {
    _iElements++;   
    }
    public void endDocument() {
        System.out.println("Document contains " + _iElements +
        " elements.");
    }
};

Listing 10. A class that counts the elements in an XML document

To create a Java program that counts elements in an XML file, you'd simply create a SAX parser (how you do that depends on your particular parser package), then create an instance of your ElementCounter class. You then call the parser's setDocumentHandler method with the new ElementCounter as an argument. The parser keeps a reference to the DocumentHandler you passed to it. When you call the parser's parse() method, the parser reads its input source. Each time it encounters an element (that is, a tag) in the XML file, it calls the startElement() method of your ElementCounter object, passing the name of the tag and a list of attributes the tag may have had.

Experimenting with SAX

An example package, com.javaworld.JavaBeans.XMLApr99, can be downloaded for free (see Resources). The sample main() program lets you specify (in this order):

  1. An XML file to parse
  2. The fully specified class name of the parser (optional)
  3. The fully specified class name of a document handler

The package includes two document handlers: the ElementCounter from Listing 10, and a handler called SimplePrinter, which (naturally) simply prints the XML with an easy-to-read indentation. You can try writing your own document handler and passing it to the main method (called com.javaworld.JavaBeans.XMLApr99.ParseDemo.main()).

You'll need the JAR file called "XMLApr99.jar," and you'll need to download the JAR file for IBM's excellent "XML for Java" package (version 2). Place both JAR files in your CLASSPATH, and type

java com.javaworld.JavaBeans.XMLApr99.ParseDemo

for instructions. The XML for Java package includes excellent documentation, a programmer's guide, and several example programs to get you started.

The source code is also available in zip and tar.gz formats. As an exercise, try downloading one of the other vendors' XML parsers from the Resources section, and then overriding the method ParseDemo.createParser() in the sample code to create a parser from the new package.

Become a tree surgeon!

One final, somewhat more advanced topic, before we close. The SAX interface allows you to parse an XML file and execute particular actions whenever certain structures (like tags) appear in the input. That's great for a lot of applications. There are times, though, when you want to be able to cut and paste whole sections of XML documents, restructure them, or maybe even build from scratch an object structure like the one in Figure 3, and then save the whole structure as an XML file. For that, you need access to the DOM API.

The DOM API allows you to represent your XML document as a tree of nodes in your Java (or other language) program. While a SAX parser reads an XML file, doing callbacks to a user-defined class, a DOM parser reads an XML file and returns a representation of the file as a tree of objects, most of which are of type org.w3c.dom.Node This gives you immense power in manipulating structured documents. Figure 4 is an example of what I'm talking about.

Figure 4. A DOM document transformation system

The Document Object Model, in the package org.w3c.dom, defines interfaces for document elements (that is, tags), DTD elements, text nodes (where the actual text inside the tags is kept), and quite a few other things we haven't even discussed. Figure 4 is a schematic of a general system that can transform one XML document to some other form programmatically. Your program uses a DOM parser to parse an XML file, and the parser returns a tree that is an exact representation of the XML in the file. Note that, at this point, you've read an input file, checked it for formatting and semantic validity, and built a complex hierarchical object structure, all in just a few lines of code. You can then traverse the document tree in software, doing whatever you like to the tree structure. Add nodes, delete them, update their values, read or set their attributes -- basically anything you like. When your tree has the new structure you desire, tell the top node to print itself to another XML file, and the new document is created.

XML-Java synergy

One of the reasons Java and XML are so well-suited for one another is that Java and XML are both extensible: Java through its class loaders, XML through its DTD. Imagine a server, reading and writing XML, where the DTD for the system input can change. When a new element is added to the input language, a running server (written in Java) could automatically load new Java classes to handle the new tags. You would not only have an extensible application server -- you wouldn't even have to take the server down to add the extensions!

One small idea points to the possible implementations of XML and Java together. The next section is about a company whose combination of XML and Java is its core technology.

XML with Java in the real world

You now have a handle on XML technology, including how it's implemented in Java. You understand that a document can be viewed as a tree of objects and manipulated using SAX or DOM. Let's have a look at a real company that is using all of these technologies to provide solutions for its clients.

DOM interfaces exist not only for XML, but for HTML, as well. This means that the leftmost document in Figure 4 could be a Web page from which you wish to extract information for manipulation in Java.

In fact, Epicentric, an Internet startup in San Francisco, does just that. Epicentric uses Java and XML in its turnkey systems to allow creation of custom portal sites. Portal sites, like the front pages of Netscape Netcenter and Excite!, are integrated aggregations of information from various Internet sources. In a corporate Internet environment, a portal may contain information gleaned from external Web pages (for example, weather reports), alongside internal enterprise data. Portals are also often customizable by each user.

Epicentric's systems read HTML from the Internet as DOM documents, extract information from those documents, and store that information in a standard XML format. Other information sources are also converted into this same XML format and stored on Epicentric's server. The company then uses the XML with XSL and Java Server Pages to create custom portals for its clients.

"A lot of good work has been done on the basics ... like parsers and XSL processors," says Ed Anuff, CEO of Epicentric. One benefit of using XML is that it makes designers think through the system structure in a very structured way, Anuff says.

When asked about concerns with XML, Anuff states that many of the problems he runs into are architectural, such as which DTD to use, and designating the appropriate places in the system to use XML. Systems designers are still working out how to use this new technology most effectively in an enterprise environment.

Also, since the technology is so new, it's often hard to know what pieces of the system to build in-house. For example, quite a few companies built their own XML parsers but now have little return on investment because larger companies are developing superior XML technology and giving it away for free. "The biggest challenge today is figuring out when you're reinventing the wheel, and when you're adding value," says Anuff.

Despite these challenges, the future looks bright for Epicentric, which has several "pretty decent-sized customers" using the company's software in beta. With clients and advertisers that include the likes of Eastman Kodak Company, Sun Microsystems, Chase Bank, and LIFE Magazine, Epicentric is using XML to aggregate and redistribute information in novel ways.

Conclusion

XML is a powerful data representation technology for which Java is uniquely well-suited. You're going to be hearing a lot about XML in the coming months and years. Anyone working with information systems that communicate with other systems (and what systems don't, these days?) has a lot to gain by understanding XML technology and using it to its full advantage.

Using XML with XSL or CSS, you can manage your Web site's content and style, and change style in one place (the style sheet) instead of editing piles of HTML files or, worse, editing the scripts that produce HTML dynamically. Using SAX or DOM, you can treat Web documents as object structures and process them in a general and clean way. Or, you can leave browsers behind entirely and write pure-Java clients and servers that talk to each other -- and other systems -- in XML, the new lingua franca of the Internet. Sun Microsystems, the creator of Java, has perhaps best described the power of XML and Java together in its slogan: Portable Code -- Portable Data. Start experimenting with XML in Java, and you'll soon wonder how you ever lived without it.

Thanks to Dave Orchard for his comments on drafts of this article, and to the many helpful people I met in San Jose, CA.

Mark Johnson lives in Fort Collins, CO, and is a C++ programmer by day and Java columnist by night. Very late night.

Learn more about this topic

Related:
1 2 3 Page 3
Page 3 of 3