So far we have defined data, and we have seen that our data can be displayed in our browser, but will our users like reading raw information? We will now begin to learn how to display XML. Note: we will not be teaching Cascading Style Sheets (CSS) here; we saw the basics of CSS in the previous chapter. We discuss only how to use them with XML.
Using CSS serves several purposes:
It improves clarity of the document when displayed.
We can write once, use often.
One change can be reflected many places.
We can present the same data in different ways for different purposes.
With a style sheet all the display rules are kept in one file that is linked to the source document. So we need to define what our display rules will be and associate them with our XML tags.
Create a new file called pdalist.css and type the following:
name { DISPLAY: block; FONT-WEIGHT: bold; FONT-SIZE: 20pt; COLOR: #9370db; FONT-FAMILY: Arial, verdana; } os { DISPLAY: block; FONT-SIZE: 16pt; COLOR: #9370db; FONT-FAMILY: Arial, verdana; } processor { DISPLAY:inline; FONT-SIZE: 14pt; COLOR: #9370db; FONT-FAMILY: Arial, verdana; } color { DISPLAY: inline; FONT-WEIGHT: bold; FONT-SIZE: 12pt; COLOR: #c71585; FONT-FAMILY: Arial, verdana; TEXT-ALIGN: Left; } height { DISPLAY: inline; FONT-STYLE: italic; FONT-SIZE: 10pt; COLOR: #9370db; FONT-FAMILY: Arial, verdana; } width { DISPLAY: inline; FONT-STYLE: italic; FONT-SIZE: 10pt; COLOR: #9370db; FONT-FAMILY: Arial, verdana; } ram { DISPLAY: inline; FONT-STYLE: italic; FONT-SIZE: 10pt; COLOR:#c71585; FONT-FAMILY: Arial, verdana; } rom { DISPLAY: inline; FONT-STYLE: italic; FONT-SIZE: 10pt; COLOR:#c71585; FONT-FAMILY: Arial, verdana; } price { DISPLAY:block; FONT-SIZE: 8pt; COLOR:#c71585; FONT-FAMILY: Arial, verdana; }
Here we have defined blocks of style to match our elements that have data. We have name, os, processor, color, height, width, ram, rom, and price. Each one of these defined elements in our XML file contains data to be displayed. Our elements, pdalist, pda, screen, pixels, and memory, are parent (node) elements. Defining styles for both in all instances would be redundant because the child definitions will take precedence over the parent element definitions. The element names we use here are the pattern-matching sections in the CSS. These will match up to our XML elements.
What makes a style work are the properties, which are between the curly braces { }. Action is taken against the matched element. Starting with our name element we have the following properties: Display, Font-Weight, Font-Size, Color and Font-Family, and many other properties. But Display is new. What does this mean? Inside the browser is a CSS forms areas, the first is the PAGE. This is the page we see when HTML or XML is rendered. Inside the page, nested, are several AREA blocks and inside an AREA are BLOCK and FLOW objects. With the CSS property, we can specify a style for the page, an area, and even a block or a flow area.
A block value for display will place that element on its own line. An inline value will display the next element on the same line as the previous one. Our elements name and os will be on separate lines because they are declared as blocks. Processor is inline, as are color, height, width, ram, and rom. Price is a block so this will be on a separate line.
All properties are specified with a colon, which delimits the property from the value. All property declarations end with a semicolon.
We could also write it so the parent element has the style defined.
name { DISPLAY: block; FONT-WEIGHT: bold; FONT-SIZE: 20pt; COLOR: #9370db; FONT-FAMILY: Arial, Verdana; } os { DISPLAY: block; FONT-SIZE: 16pt; COLOR: #9370db; FONT-FAMILY: Arial, Verdana; } processor { DISPLAY:block; FONT-SIZE: 14pt; COLOR: #9370db; FONT-FAMILY: Arial, Verdana; } screen { DISPLAY: block; FONT-WEIGHT: bold; FONT-SIZE: 12pt; COLOR: #c71585; FONT-FAMILY: Arial, Verdana; TEXT-ALIGN: Left; } memory { DISPLAY: block; FONT-STYLE: italic; FONT-SIZE: 10pt; COLOR: #9370db; FONT-FAMILY: Arial, Verdana; } price { DISPLAY:block; FONT-SIZE: 8pt; COLOR:#c71585; FONT-FAMILY: Arial, Verdana; }
Save this as pdalist2.css.
We now have our pdalist.xml and a pdalist.css. We need to tie the two together so we can display our XML with style!
We need to make a declaration in our XML file so when it loads, the CSS file can be used. Let's open our pdalist4.xml file and add the following line after our XML declaration. Save this file as pdalist4.xml.
<?xml-stylesheet href="pdalist.css" type="text/css"?>
When we open our XML file in IE, we should see the screen shown in Figure 14-6.
Figure 14-7 shows how our file will look in Netscape.
You can see that the elements for color, height, and width all have the same formatting, unlike our screenshot in Figure 14-7. This is because we defined our parent element screen, and it cascades down to the subelements.
Change the style sheet declaration to the following, so we can use our second CSS.
<?xml-stylesheet href="pdalist2.css" type="text/css"?>
Go back and look at what we did for our pdalist2.css. All elements are to display as blocks, but also take note that we defined styles for those elements that had subelements: memory, which has ram and rom; screen, which has color; and pixels, which has the subelements height and width. Figure 14-8 shows what our display will look like in Netscape, and Figure 14-9 shows our results in IE.
Let's look at how we can use XSL to format the results of the XML parsing.
XSLT is a template-based programming language that allows us to restructure our content to create the look we require. XSLT transformations can enable different kinds of software applications to exchange data. They can also be used to generate multiple views of the same source document to enable a website's content to be displayed on a myriad of devices.
XSLT's elements and attributes provide a declarative programming language for processing XML data. We can use XSLT's vocabulary to grab content from other documents, create new elements and attributes or, more commonly, some combination of the two.
An XSLT 1.0 transformation requires two starting documents (an XML source document and an XSLT style sheet) to produce a single result document. Note that the forthcoming XSLT 2.0 won't require this. The process begins when an XSLT style sheet is applied to an XML document's source tree to generate a result tree that is usually saved as an XML or HTML document. (See Figure 14-10.)
Note I have simplified our original example and removed the screen elements.
An XSLT style sheet contains template rules that define the following:
The criteria for selecting elements from the source tree
Instructions for restructuring the selected content to create the result tree
Template rules are the key building blocks of XSLT transformations. A template rule has two parts: a pattern and a template. The pattern (usually an element name) is then matched against elements in the source tree to determine which nodes to select for processing. The template provides instructions for processing the selected content.
Each template rule constructs a result tree fragment of markup and content. An XSLT transformation's result tree is created when all of the result tree fragments are combined in the order specified to form a completed whole.
Now let's go through an example style sheet and get into more detail about XSLT's template rules.
Our XSLT style sheet document needs to include an XML version declaration (just like any other XML document.
<?xml version="1.0" encoding="iso-8859-1"?>
Next, we will declare XSLT's namespace prefix. XSLT's namespace-prefixed elements enable an XSLT processor to distinguish them from other kinds of markup in the style sheet, such as the HTML elements contained within a template rule.
XSLT's namespace prefix is declared within the stylesheet's root element, which is allowed to be either xsl:stylesheet or xsl:transform.
An XSLT version attribute should be included between the root element and the xsl namespace-prefix declaration.
The XSLT namespace is identified by its unique URI value (http://www.w3.org/1999/XSL/Transform), not by the xsl prefix.
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
Now that we have our namespace prefix declared, we can go about creating some template rules that will be used to transform our source glossary document into an HTML table. Much like an old fashioned mail merge, the HTML markup fragments in the following template provide the XSLT processor with a model for restructuring our source content.
The xsl:template element is used to encapsulate template rules. The value of its match attribute contains an XPath statement that is used as a pattern to select source elements for processing. A document's first template almost always has a match value of /, which means the document root.
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html> <head> <title>Review Of Palm PCs</title> </head> <body> <h4>List Of Palm/Pocket PCs</h4> <table width="100%" border="1"> <thead> <tr> <th>Name</th> <th>OS</th> <th>Processor</th> <th>Memory (RAM/ROM)</th> <th>Price</th> </tr> </thead> <tbody> <xsl:apply-templates/> </tbody> </table> </body> </html> </xsl:template>
The apply-templates element signals an XSLT processor to look for other template rules and apply them at that point in the style sheet's structure. The results of each rule combines to form the result tree of the completed transformation.
The following template matches each <pda> entry in the XML pdalist file, and creates table rows until it runs out of item elements to process.
<xsl:template match="pda"> <tr> <td><strong> <xsl:value-of select="name" /></strong></td> <td><xsl:value-of select="os" /></td> <td><xsl:value-of select="processor" /></td> <td><xsl:value-of select="memory" /></td> <td><xsl:value-of select="price" /></td> </tr> </xsl:template> </xsl:stylesheet>
Notice how the value-of element also uses a select attribute to choose the content from the source document we wish to use to create our result document.
Our finished XSL file should look like this:
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html> <head> <title>Review Of Palm PCs</title> </head> <body> <center><h4>List Of Palm/Pocket PCs</h4></center> <table width="100%" border="1"> <thead> <tr> <th>Name</th> <th>OS</th> <th>Processor</th> <th>Memory (RAM/ROM)</th> <th>Price</th> </tr> </thead> <tbody> <xsl:apply-templates/> </tbody> </table> </body> </html> </xsl:template> <xsl:template match="pda"> <tr> <td><strong> <xsl:value-of select="name" /></strong></td> <td><xsl:value-of select="os" /></td> <td><xsl:value-of select="processor" /></td> <td><xsl:value-of select="memory" /></td> <td><xsl:value-of select="price" /></td> </tr> </xsl:template> </xsl:stylesheet>
Be sure to save it as pdalist.xsl.
An XML processing instruction is used to associate an XML document with a Cascading Style Sheet (CSS) or XSL Transformations (XSLT) style sheet. The syntax used is identical except for the value of the type attribute, which will be either "text/css" or "text/xsl" depending on which flavor style sheet is used.
Following are the two variations side-by-side to illustrate the different values of the type attribute.
<?xml-stylesheet type="text/xsl" href="pdalist.xsl"?> <?xml-stylesheet type="text/css" href="pdalist.css"?>
The correct placement of the style sheet declaration is within a document's prologue (after the XML declaration and before the root element).
Now we need to alter our .xml file and tell it to refer to the .xsl file. Open up pdalist4.xml and alter the top part as shown here:
<?xml version="1.0" encoding="iso-8859-1"?> <?xml-stylesheet type="text/xsl" href="pdalist.xsl"?> <!DOCTYPE pdalist SYSTEM "pdalist.dtd"> <pdalist> <pda> .. ...
Apart from deleting the reference to our .css file and adding a reference to the .xsl file, the remainder of the file remains the same. Save the file as pdalist5.xml and load it into IE, and we'll see the page shown in Figure 14-11.
Loaded into Netscape 7, we see the page shown in Figure 14-12.
It has to be said that IE 6 is much more descriptive in its error details if we do make a mistake. Netscape generally just tells us a mistake has been made but leaves it up to us to find out where.