![]() Capt. Horatio T.P. Webb | Displaying XML (and an introduction to XSL) Parks -- FALL 2000 Last Updated 12PM 9/13/2000 | |
There are several ways to display XML data in the browser:
IE5 and later will parse and display an XML file just by loading it into the browser.
Just click http://www.bauer.uh.edu/parks/jv.xml to see the XML.
We can use the facility of the Document Object Model (DOM) to access the contents of an XML document embedded inside HTML. This requires three steps:
First you surround the XML data with <XML> and </XML> tags. We can take an XML document like:
|
<?xml version="1.0"?> <family> <dad>Fred</dad> <mom>Alice</mom> <son>John</son> </family> |
To make the data island we surround the XML with IE5's <XML> tags with an id. Like:
|
<XML id="data_island"> <?xml version="1.0"?> <family> <dad>Fred</dad> <mom>Alice</mom> <son>John</son> </family> </XML> |
Note that the <XML> tags are IE5 specific -- not part of XML proper.
<HTML>
<BODY onLoad="ol()">
<DIV Id="data_island_destination">
</DIV>
<SCRIPT language="javascript">
function ol()
{
var root=data_island.documentElement;
if (data_island.parseError !=0)
alert(data_island.parseError.reason);
xml_string="root="+root.nodeName;
for (i=0;i<root.childNodes.length;i++)
{
nn=root.childNodes.item(i).nodeName;
xml_string=xml_string+"<br> node-number="+i;
xml_string=xml_string+" nodeName="+nn;
xml_string=xml_string+" content-of-the-node="+root.childNodes.item(i).text;
}
data_island_destination.innerHTML = xml_string;
}
</SCRIPT>
Putting it all together we get:
|
<HTML> |
Try this by clicking here
We have used the DOM to get a handle for the XML (data_island), then roll through the XML with a loop. First we get the root name:
xml_string="root="+root.nodeName;
Now loop thru its children:
for (i=0;i<root.childNodes.length;i++)
adding the node number, nodeName and data to a string (xml_string) as we walk the tree. First get the node name:
nn=root.childNodes.item(i).nodeName;
Now package it in HTML:
xml_string=xml_string+"<br> node-number="+i;
xml_string=xml_string+" nodeName="+nn;
then add the data:
xml_string=xml_string+root.childNodes.item(i).text;
After the loop terminates, we hand the string to the container (data_island_destination):
data_island_destination.innerHTML = xml_string;
Not pretty, but gets the job done (i.e., rolls the data out to HTML from the XML data island). Note the key here is the use of the nodelist components:
To connect (bind) the XML data with specific HTML elements, we build an XML data island as in the previous case. It has:
Here is our family XML file with ID= "data_island":
|
<XML id="data_island"> <?xml version="1.0"?> <family> <dad>Fred</dad> <mom>Alice</mom> <son>John</son> <son>Alfred</son> <daughter>Mary</daughter> </family> </XML> |
Remember the <XML> tags are IE5 specific -- not part of XML proper.
To bind to HTML we can connect (i.e., bind) the HTML elements on the page to specific tags in this XML data island. In general we include:
The format is:
<html-tag DATASRC="#id-attribute of the <XML> tag" DATAFLD="XML tag name to provide the data">
The HTML tags that can be bound to the XML are:
| HTML TAG | Property | Can be Updated? |
Displayed As |
| input type=checkbox | checked | YES | text |
| input type=hidden | value | ||
| input type=password | value | ||
| input type=radio | checked | ||
| input type=text | value | ||
| input type=label | value | ||
| select | text of selected option | ||
| textarea | value | ||
| applet | parameter | ||
| object | parameter | ||
| button | innerText AND innerHTML | NO | HTML |
| label | |||
| div | |||
| marquee | |||
| span | |||
| a | href | text | |
| frame | src | ||
| iframe | |||
| img |
Thus we can bind simple XML data to HTML element in many ways. Here is the simply family-address XML data island:
|
<XML id="data_island"> <?xml version="1.0"?> <family-address> <family-name>Turing</family-name> <street>Turing Lane</street> <city>Princeton</city> <state>NJ</state> <zip>11111</zip> </family-address> </XML> |
If we wished the family-address data to be bound to text boxes, the HTML would look like:
|
Family <input type="text" size="20" DATASRC="#data_island" DATAFLD="family-name"> Street <input type="text" size="20" DATASRC="#data_island" DATAFLD="street"> City <input type="text" size="20" DATASRC="#data_island" DATAFLD="city"> State <input type="text" size="2" DATASRC="#data_island" DATAFLD="state"> Zip <input type="text" size="5" DATASRC="#data_island" DATAFLD="zip"> |
Putting the two together, we get this. Works well. This approach works if we have one HTML tag for each XML tag. This is ok in some cases, but when there are multiple occurences of an XML tag this isn't going to work.
The HTML <table> tag solves this problem of multiple XML tags (i.e., nesting). Note the table element is not in the previous list of definitions of HTML elements that can bind to XML data. The table tag is special since it can bind to multiple occurences of XML tags. To "tabularize the XML" (i.e., bind the data to a table), we include only the DATASRC in the <table> tag itself. Then for each recurring section of the XML file, we specify BOTH a DATASRC and DATAFLD. To demonstrate this, we include two families in our family-address XML file and call it all a neighborhood:
|
<XML id="data_island"> <?xml version="1.0"?> <neighborhood> <family-address> <family-name>Turing</family-name> <street>Turing Lane</street> <city>Princeton</city> <state>NJ</state> <zip>11111</zip> </family-address> <family-address> <family-name>Godel</family-name> <street>Computable Avenue</street> <city>Princeton</city> <state>NJ</state> <zip>11111</zip> </family-address> </neighborhood> </XML> |
Now we create a table structure in HTML:
|
<table border='1"><tr><td> <table DATASRC="#data_island"> <tr><td>MY NEIGHBORHOOD</td><tr> <tr>
Family <input type="text" size="20" DATASRC="#data_island" DATAFLD="family-name">
</tr> |
Now each row of table has a complete family-address. Look at this.
The basic idea is to use a style sheet specification in the xml file. This involves adding a single line to the xml file. This line contains a link to the style sheet where the CSS is defined for the elements of the XML file. Generally this looks like:
<?xml-stylesheet type="text/css" href="URL_of_the_stylesheet"?>
We can make a style sheet that specifies for each ELEMENT type some style options. For our <family> xml file we could say:
|
family {display:block} dad {display:inline ; color: red} mom {display:inline ; color: blue} son {display:inline ; color: brown} daughter {display:inline ; color: green} |
This style sheet file is saved as: xmltest.css
Now we just insert this style sheet reference into the original XML file and we get:
|
<?xml version="1.0"?> <?xml-stylesheet type="text/css" href="xmltest.css"?> <family> <dad>Fred</dad> <mom>Alice</mom> <son>John</son> <son>Alfred</son> <daughter>Mary</daughter> </family> |
Click here to see the results. Simple.
XSL is a style language for XML in the same way CSS is a style language for HTML. First we add an XSL style sheet reference to the XML file just as we did in the previous example. Except the type is XSL not CSS. The general form is:
<?xml-stylesheet type="text/xsl" href="URL_of_the_stylesheet"?>
We can make up the simpliest XSL stylesheet as follows:
|
<?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl"> <xsl:template match="/"> <xsl:value-of /> </xsl:template> </xsl:stylesheet> |
and save it as xmltest.xsl. The "template match" line attempts to find "/" (i.e., the document root). The "value of /" line starts at the root and inserts all the descendants of the root element (i.e., everything). So the original XML file appears as:
|
<?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="xmltest.xsl"?> <family> <dad>Fred</dad> <mom>Alice</mom> <son>John</son> <son>Alfred</son> <daughter>Mary</daughter> </family> |
Click here to see the simple XSL presentation. Click here for the XSL stylesheet. Not interesting -- but this is the basic roll-out for dumping an XML file.
The general idea of XSL is the use of templates to find the elements of the XML file and then to format the tag contents with specific HTML.
We can use more advanced features of XSL. We can apply other templates to match other than root (i.e. /). We can only parse the <son> and <daugther> tags only like:
|
<?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl"> <xsl:template match="/"> <p STYLE="{color:green}">For the family:</p> <xsl:apply-templates select="//son" /> <xsl:apply-templates select="//daughter" /> </xsl:template> <xsl:template match="son"> <p STYLE="{color:blue}">a son named <xsl:value-of /> was found.</p> </xsl:template> <xsl:template match="daughter"> <p STYLE="{color:red}">a daughter named <xsl:value-of /> was found.</p> </xsl:template> </xsl:stylesheet> |
Note that the first section says to match all child nodes of the root (template match="/"). Immediately upon matching the root, we provide a green STYLE tag. While performing this operation of retreiving all the children of root, we only select sons and daugthers (the two lines that say: apply-templates select=//tag name to match /). The second and third sections show what to do when a match occurs (template match="tag name to match"). Note that in each matched section there is HTML provided to surround the tag value. In this case we provide a <p> tag with style. The "value-of /" tag inserts the content for the match.
Saving this XSL stylesheet as xmltest2.xsl and modifying the original file to reflect this style sheet, we get:
|
<?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="xmltest2.xsl"?> <family> <dad>Fred</dad> <mom>Alice</mom> <son>John</son> <son>Alfred</son> <daughter>Mary</daughter> </family> |
Click here to see the new XML with a green family text at the root, red son values and blue daughter values. Click here for the XSL stylesheet.
To extend this XSL example, we will use a more complicated XML file composed of a town with multiple families where each family has a surname. Here is a "town" of two "families":
|
<?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="xmltest3.xsl"?> <town> <family> <surname>Jones</surname> <dad>Fred</dad> <mom>Alice</mom> <son>John</son> <son>Alfred</son> <daughter>Mary</daughter> </family> <family> <surname>Smith</surname> <dad>Bill</dad> <mom>Jill</mom> <son>Will</son> <son>Phil</son> <daughter>Millie</daughter> <daughter>Tillie</daughter> </family> </town> |
Here is an XSL stylesheet for the multifamily town:
|
<?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl"> <xsl:template match="/"> <p STYLE="{color:green}"><b>For the town:</b></p> <xsl:apply-templates select="//family" /> </xsl:template> <xsl:template match="family"> <table border='1'><tr><td>FAMILY: <xsl:apply-templates select=".//surname" /> <xsl:apply-templates select=".//dad" /> <xsl:apply-templates select=".//mom" /> <xsl:apply-templates select=".//son" /> <xsl:apply-templates select=".//daughter" /> </td></tr></table><p></p> </xsl:template> <xsl:template match="surname"> <b> <xsl:value-of /> </b> </xsl:template> <xsl:template match="dad"> <tr><td><p STYLE="{color:black}">dad= <xsl:value-of /> </p></td></tr> </xsl:template> <xsl:template match="mom"> <tr><td><p STYLE="{color:pink}">mom= <xsl:value-of /> </p></td></tr> </xsl:template> <xsl:template match="son"> <tr><td colspan='2'><p STYLE="{color:blue}">son= <xsl:value-of /> </p></td></tr> </xsl:template> <xsl:template match="daughter"> <tr><td colspan='2'><p STYLE="{color:red}">daughter= <xsl:value-of /> </p></td></tr> </xsl:template> </xsl:stylesheet> |
Note that inside the root template (i.e., between the first template tags), the matching of root produces a green title for the town. Inside this template, all family tags are selected. The next template pair shows what to do with each family:
Note the use of ".//" instead of "//" in the select templates. ".//" implies the current node only -- not all nodes (i.e., .//surname produces the surname tag for THIS CURRENT family -- NOT all surnames tags).
Click here for the output. Click here for the XSL stylesheet.