Displaying XML in Internet Explorer
October 25, 2000
Q: How can I view XML using Internet Explorer 5.0? When I try, only the tags are visible but not the contents. I've written an XSLT stylesheet also, but it is not working.
A: (Laughing) Yeah, that's always a problem with all these darned languages: They insist on being understood.
Before considering some ideas to unravel your confusion, you need to understand one very important thing about Internet Explorer 5.0. The "XSL processor" built into it is not compliant with the final XSLT Recommendation. To bring it up to speed, you need to install the very latest of a series of so-called preview releases of a component, msxml.dll, available from the Microsoft site at http://msdn.microsoft.com/xml/general/msxmlprev.asp. By common consensus on the XSL-List mailing list, the very best source of information on how to install this correctly is Joshua Allen's Unofficial MSXML XSLT FAQ .
Once you've taken care of these preliminaries, you can follow along with the answer to your question. I don't know what your XML looks like, of course. But let's say you've got a document that looks like this:
<?xml version="1.0"?> <family> <grandparent gender="male"> <persname>Morris</persname> <parent gender="female"> <name>Betty</name> <child gender="male"> <persname>John</persname> </child> <child gender="female"> <persname>Connie</persname> </child> <child gender="female"> <persname>Cindy</persname> </child> <child gender="male"> <persname>Mike</persname> </child> </parent> </grandparent> </family>
The general idea is that it repressents a bloodline descending through three generations, from a grandparent, through his daughter, to her four children. If you look at this with Internet Explorer 5+, you see a collapsible/expandable tree of markup and content. Click on a minus sign to collapse that branch of the tree, at which point the minus turns into a plus. Click on a plus to expand the tree. This quasi-interactive view of the document isn't built into XML; it's the result of a stylesheet built into IE5+ -- specifically, the aforementioned msxml.dll component. (To see the stylesheet, enter this URL into IE's "Address" field: res//msxml.dll/defaultss.xsl.) Remember, though, that this default stylesheet isn't XSLT. To construct a simple stylesheet written in genuine XSLT, read on.
This will supply you only with the XSLT basics. For a comprehensive, easy-to-follow tutorial, read Bob DuCharme's ongoing series, "Transforming XML," here on xml.com.
An XSLT stylesheet is itself an XML document. Among its elements and attributes are those that represent XSLT instructions for how to transform the source XML into some result, which -- in the case of IE5+, especially -- will typically be well-formed HTML.
The root element of an XSLT stylesheet is called xsl:stylesheet. A bare-bones version of this element looks like the following.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/TR/REC-html40"> </xsl:stylesheet>
The version attribute says that this stylesheet conforms to version 1.0 of the XSLT standard. The two attributes whose names begin with "xmlns" are namespace declarations. The first one, xmlns:xsl, tells the XSLT processor that any elements whose names begin with the prefix "xsl:" (including the colon, like the xsl:stylesheet element itself) are XSLT elements. The second, xmlns, declares that any elements whose names do not begin with a prefix will be HTML 4.0 elements. This is what we want here because with IE you generally want to display a Web page. In effect, the stylesheet will convert all XML code to HTML.
Let's say you want to apply this bare-bones stylesheet to your document. You've got one more step, which is to add a processing instruction (PI) to your document. This PI will tell IE what kind of stylesheet you're using, CSS or XSLT, and where to find it. Let's say the stylesheet is called family.xsl, and it's in the same directory as the document itself. The document with this PI looks like this:
<?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="family.xsl"?> <family> <grandparent gender="male"> [etc.]
Now when you open the document, you won't see any tags at all, only content. It will look like
This is the opposite of the problem you've described in your question, and probably doesn't seem like much progress at all. What's going on here is that the XSLT standard prescribes a series of built-in rules for how to transform the source document. According to these built-in rules, for example, an element's content is displayed, but attribute values are not. So what you're seeing is the content of all the elements displayed contiguously.
To specify specific processing for specific elements, you add a series of template rules to your stylesheet. Each template rule tells the XSLT processor to which portion of the source document the rule applies and provides a template (hence the term "template rule") for what to create in the "result tree" (a corresponding portion of an HTML document in this case).
We're going to use two simple template rules to create an HTML table from our source document. The table will consist of three columns: one for the relationship (grandparent, parent, or child), one for the name of the person who has that relationship, and one for that person's gender. The first template rule:
<xsl:template match="/family"> <table border="1" summary="Family tree"> <tr> <th>Relationship</th> <th>Name</th> <th>Gender</th> </tr> <xsl:apply-templates select="grandparent"/> </table> </xsl:template>
Reading down through the template rule, it says
- This template rule applies to the root "family" element only
- When you find such an element, construct an HTML table.
- Add a row to the table, with table header cells for the values to be displayed.
- Process the element named "grandfather" which is a child of the root "family" element.
Note the placement of the xsl:apply-templates element which performs step 4. The grandfather element will be processed after the initial table row has been created; this is important for enabling the second template to create additional rows, one per element.
The second template rule not only processes the "grandfather" element but also any "parent" or "child" elements in the document.
<xsl:template match="grandparent|parent|child"> <tr> <td><xsl:value-of select="name()"/></td> <td><xsl:value-of select="persname"/></td> <td><xsl:value-of select="@gender"/></td> </tr> <xsl:apply-templates select="parent|child"/> </xsl:template>
Again reading top to bottom, this template rule says
- The template rule applies to elements named "grandparent," "parent," or "child"
- When you find one of these elements, immediately set up a table row and three table cells
- In the three table cells, display the name of the element being processed, the value of that element's "persname" child element, and the value of the "gender" attribute
- Close the table row
- Process any children of the current element whose names are "parent" or "child"
The last step above is important. Note that, in effect, it makes the template rule recurse until all elements in the source document have been processed.
IE displays the result of this stylesheet thus:
Once you've got the hang of this simple application (and have read DuCharme's "Transforming XML" to alert you to the subtleties and more advanced features of XSLT), you should be able to extend it easily for your individual purpose.