XML CSS DTD
XML CSS DTD
The XML specification was created by the World Wide Web Consortium (W3C), the body that sets standards for the web.
Features/Benefits of XML
XML has been widely adopted since its creation and with good reason. Some of the key features and benefits of XML include:
y
y y
Easy data exchange - One of the great things about XML is that it can allow easy sharing of data between different applications - even if these applications are written in different languages and reside on different platforms. Self-describing data - When you look at an XML document, it is very easy to figure out what's going on. Create your own languages - XML allows you to specify your own markup language for your own specific purpose. Some existing XML based languages include Banking Industry Technology Secretariat (BITS), Bank Internet Payment System (BIPS), Financial Exchange (IFX) and many more.
HTML
HTML includes over 100 pre-defined tags to allow the author to specify how each piece of content should be presented to the end user. For example, if you surround some content with <b></b> tags, the user agent/browser will render that content using a bold typeface.
XML
XML allows you to create your own tags to describe the data between them. You're not particularly interested in how the data will be presented. Your main focus is ensuring that the data is well organised within descriptive tags (or elements). This is because XML is primarily used for data storage and transfer purposes - not for presentation purposes. While you can view XML documents with a simple text editor, there are free XML viewers that present the contents in a more readable form. XML viewers interpret the document so it will display the XML document using any styles that have been applied using XSLT or CSS. It will also warn you if something doesn't look right, or if it doesn't validate correctly. Most modern browsers include XML support, so it's quite possible that your own browser is able to display the contents of XML files. You open an XML file in your browser the same way you open any other file in your browser. If it's a local file you can type the full path into the address bar. Otherwise, if it's available over the web, you can type the URL into the address bar.
Notepad
You can use a text editor such as Notepad to create or view a simple XML file. Here's what this XML file looks like in Notepad:
Firefox
Here's how the above XML file appears in Firefox 2.0. Notice the difference between Notepad and Firefox. Firefox actually attempts to interpret the document. It even warns us if it thinks something could be out of place (such as a missing stylesheet).
Internet Explorer
Here's how the same XML file appears in Internet Explorer 6.0
Displaying Errors
If your XML document contains an error, your XML viewer should display a message indicating the error. In this file, I have purposely included an error. Below is how the error is reported in Internet Explorer.
Adding Styles
Once you start adding styles to your XML, you'll see a huge difference in how your XML documents appear with an XML viewer. We'll cover styles later.
XML Editors
As you saw in the previous lesson, you can create XML documents using a simple text editor such as Notepad, WordPad, vi, emacs, or SimpleText etc. Text editors are OK, but if you're serious about creating XML, you'd be better off finding an XML editor.
XML Notepad XML Cooktop XML Pro XML Spy Liquid XML Studio - Advanced XML development environment containing all the tools needed for designing and developing XML Schemas and applications.
XML Documents
This lesson shows you how XML documents are constructed. Similar to an HTML document, XML documents consist of stuff at the top of the document, followed by the content. Consider the following XML example:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE document system "tutorials.dtd"> <!-- Here is a comment --> <?xml-stylesheet type="text/css" href="myStyles.css"?> <tutorials> <tutorial> <name>XML Tutorial</name> <url>http://www.quackit.com/xml/tutorial</url> </tutorial> <tutorial> <name>HTML Tutorial</name> <url>http://www.quackit.com/html/tutorial</url> </tutorial> </tutorials>
The following table provides an explanation of each part of the XML document in the above example: XML Declaration standalone="no"?> Document Type <!doctype document system "tutorials.dtd"> Definition (DTD) Prolog <!-- Here is a comment --> Comment (optional) Processing <?xml-stylesheet type="text/css" href="myStyles.css"?> Instructions White Space Elements & Root element <tutorials> opening tag Content
<?xml version="1.0" encoding="UTF-8"
(required)
</tutorials>
Prolog
Right at the top of the document, we have a prolog (also spelt prologue). A prolog is optional, but if it is included, it should become at the beginning of the document. The prolog can contain things such as the XML declaration, comments, processing instructions, white space, and document type declarations. Although the prolog (and everything in it) is optional, it's recommended that you include the XML declaration in your XML documents.
XML Declaration
The XML declaration indicates that the document is written in XML and specifies which version of XML. The XML declaration, if included, must be on the first line of the document. The XML declaration can also specify the language encoding for the document (optional) and if the application refers to external entities (optional). In our example, we specify that the document uses UTF-8 encoding (although we don't really need to as UTF-8 is the default), and we specify that the document refers to external entities by using standalone="no". This is not a standalone document as it relies on an external resource (i.e. the DTD). Although the XML declaration is optional, the W3C recommends that you include it in your XML documents. In any case, you'll need the XML declaration to successfully validate your document.
DTDs can be internal (i.e. specified within the document) or external (i.e. specified in an external file). In our example, the DTD is external.
Comments
XML comments begin with <!-- and end with -->. Similar to HTML comments, XML comments allow you to write stuff within your document without it being parsed by the processor. You normally write comments as an explanatory note to yourself or another programmer. Comments can appear anywhere within your document.
Processing Instructions
Processing instructions begin with <? and end with ?>. Processing instructions are instructions for the XML processor. Processing instructions are not built into the XML recommendation. Rather, they are processor-dependant so not all processors understand all processing instructions. Our example is a common processing instruction that many processors understand. The instructions to the processor is to use an external style sheet.
White Space
White space is simply blank space created by carriage returns, line feeds, tabs, and/or spaces. White space doesn't affect the processing of the document, so you can choose to include whitespace or not. Technically speaking, the XML recommendation specifies that XML documents use the UNIX convention for line endings. This means that you should use a linefeed character only (ASCII code 10) to indicate the end of a line. Speaking of white space, there is a special attribute (xml:whitespace) that you can use to preserve whitespace within your elements (but we won't concern ourselves with that just now).
These are the elements that are contained within the root element. Elements are usually represented by an opening and closing tag. Data and other elements reside between the opening and closing tag of an element. Although most elements contain an opening and closing tag, XML allows you to use empty elements. An empty element is one without a closing tag. You might be familiar with some empty elements used in HTML such as the <img> element or the <br> element. In XML, you must close empty elements with a forward slash before the > symbol. For example, <br />. Elements can also contain one or more attributes. An attribute is a name/value pair, that you place within an opening tag, which allows you to provide extra information about an element. You may be familiar with attributes in HTML. For example, the HTML img tag requires the src attribute which specifies the location of an image (eg, <img src="myImage.gif" />).
XML Syntax
XML syntax refers to the rules that determine how an XML application can be written. The XML syntax is very straight forward, and this makes XML very easy to learn. Below are the main points to remember when creating XML documents.
Well-formedness
The W3C specifies that all XML documents must be well-formed. Specifically, a textual object is a well-formed XML document if:
y y y
Taken as a whole, it matches the production labeled document It meets all the well-formedness constraints given the XML specification Each of the parsed entities which is referenced directly or indirectly within the document is well-formed
If this all sounds confusing, don't worry too much. Basically, all you need to do is ensure you build your XML applications correctly!
XML Declaration
If you include an XML declaration, it must be the first item in your document. The XML declaration uses the <?xml?> element. Example:
XML Markup
Generally speaking, an XML document consists of markup and data. Markup is provided in the form of tags and attributes. Data is the text that goes in between the tags or is provided within their attributes. The next couple of lessons cover the key syntax rules related to elements and attributes.
XML Elements
XML elements are represented by tags. Elements usually consist of an opening tag and a closing tag, but they can consist of just one tag. Opening tags consist of <, followed by the element name, and ending with >. Closing tags are the same but have a forward slash inserted between the less than symbol and the element name. Example:
<tag>Data</tag>
Empty elements are closed by inserting a forward slash before the greater than symbol. Example of empty tag:
<tag />
The following syntax rules are important to note, especially if you're used to working with HTML where you don't usually need to worry about these rules.
If you're familiar with HTML, you will know that some HTML tags don't need to be closed. In XML however, you must close all tags. This is usually done in the form of a closing tag where you repeat the opening tag, but place a forward slash before the element name (i.e. </child>). If you are using an empty element (i.e. one with no closing tag), you need to place a forward slash before the greater than symbol at the end of the tag (i.e. <child />).
Example for opening/closing tags: <child>Data</child> Example for empty elements: <child attribute="value" />
Element Names
You can use any name you like for your elements as long as they adhere to the following rules: y y y y Element names can contain any character (including letters and numbers) Element names must not contain spaces Element names must not begin with a number or punctuation character (for example a comma or semi-colon etc) Element names must not start with the letters xml (whether lowercase, uppercase, or mixed case)
You shouldn't use a colon (:) in your element names, as this is reserved for another purpose.
XML Attributes
The previous lesson covered the syntax rules related to XML elements. XML elements can also contain attributes. You use attributes within your elements to provide more information about the element. These are represented as name/value pairs. Example:
<tag attribute="value">Data</tag>
It's important to remember the following syntax rules when using attributes.
Quotes
You must place quotation marks around the attribute's value. Wrong:
<tutorials type=Web> <tutorial> <name>XML</name> </tutorial> </tutorials>
Right:
<tutorials type="Web"> <tutorial> <name>XML</name> </tutorial> </tutorials>
Shorthand Is Prohibited
Attributes must contain a value. Some HTML coders like to use shorthand, where if you provide the attribute name without a value, it will equal true. This is not allowed in XML. Wrong:
<tutorials published> <tutorial> <name>XML</name> </tutorial> </tutorials>
Right:
<tutorials published="true"> <tutorial> <name>XML</name> </tutorial> </tutorials>
You might notice that, apart from some basic formatting, it doesn't look much different to viewing the file in a text editor such as Notepad. This is to be expected because the browser doesn't know anything about how our tags/elements should appear so it just displays it as is. Actually, Firefox even provides us with a message stating that the document has no style information associated with it. In order to change this, we need to specify some styles that stipulate how our XML should be displayed. We can do this using Cascading Style Sheets (CSS). If you're familiar with HTML, you'll probably know that CSS is used for adding styles to HTML documents. You can also use CSS to add styles to XML documents. If you're not familiar with CSS, you might like to read the CSS Tutorial.
Applying CSS
This XML document has been styled using CSS. If your browser supports XML and CSS, it should look something like this:
How To Do That?
You need two files: The XML file, and a CSS file. In your XML document, you need to add one line of code. This one line of code tells the processor to display the XML using styles from the external style sheet. Step 1: Create an XML file with the following content and save it:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml-stylesheet type="text/css" href="tutorials.css"?> <tutorials> <tutorial> <name>XML Tutorial</name> <url>http://www.quackit.com/xml/tutorial</url> </tutorial> <tutorial> <name>HTML Tutorial</name> <url>http://www.quackit.com/html/tutorial</url> </tutorial> </tutorials>
In order to style our XML document (which contains the 4 elements tutorials, tutorial, name and url), we can simply add those elements to our style sheet, followed by the styles we want to be applied to that element. If we don't need to style an element, we can omit it from the style sheet. Step 2: Create a file with the following content and save it as tutorials.css into the same directory as the XML file.
tutorials
{ margin:10px; background-color:#ccff00; font-family:verdana,helvetica,sans-serif; } name { display:block; font-weight:bold; } url { display:block; color:#636363; font-size:small; font-style:italic; }
Now, when you view your XML file in a browser, it should be styled using the styles from the CSS file.
XSLT Example
Using our previous XML example, imagine if we wanted to add a heading and some text to the top of the document when we output our XML document. Something like this:
The only problem is, the heading and the text isn't in the XML file. Well, this is where XSLT comes in. Using XSLT, all we need to do is create a style sheet that transforms the XML into HTML and adds the heading/text.
How to Do This?
Instead of linking to a CSS file, we will link to a XSL file. Step 1: Create an XML file with the following content and save it.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml-stylesheet type="text/xsl" href="tutorials.xsl"?> <tutorials> <tutorial> <name>XML Tutorial</name> <url>http://www.quackit.com/xml/tutorial</url> </tutorial> <tutorial> <name>HTML Tutorial</name> <url>http://www.quackit.com/html/tutorial</url> </tutorial> </tutorials>
Step 2: Create a file with the following content and save it as tutorials.xsl into the same directory as the XML file.
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/"> <html> <head> <title>XML XSL Example</title> <style type="text/css"> body { margin:10px; background-color:#ccff00; font-family:verdana,helvetica,sans-serif; } .tutorial-name { display:block; font-weight:bold; } .tutorial-url { display:block; color:#636363; font-size:small; font-style:italic; } </style> </head> <body> <h2>Cool Tutorials</h2> <p>Hey, check out these tutorials!</p> <xsl:apply-templates/> </body> </html> </xsl:template> <xsl:template match="tutorial"> <span class="tutorial-name"><xsl:value-of select="name"/></span> <span class="tutorial-url"><xsl:value-of select="url"/></span> </xsl:template> </xsl:stylesheet>
I don't expect you to understand all this code just yet. I'll be explaining that later on - I've written a whole section on XSLT. But, it does give you an hint of what's to come in this tutorial. In the above XSL file, I'm using XSLT and XPath - both of which are explained later in this tutorial.
XML Namespace
In XML, a namespace is used to prevent any conflicts with element names. Because XML allows you to create your own element names, there's always the possibility of naming an element exactly the same as one in another XML document. This might be OK if you never use both documents together. But what if you need to combine the content of both
documents? You would have a name conflict. You would have two different elements, with different purposes, both with the same name.
We will encounter a problem if we try to combine the above documents. This is because they both have an element called title. One is the title of the book, the other is the title of the HTML page. We have a name conflict. What we can do to prevent this name conflict is, create a namespace for the XML document.
Example Namespace
Using the above example, we could change the XML document to look something like this:
<bk:books xmlns:bk="http://somebooksite.com/book_spec"> <bk:book> <bk:title>The Dream Saga</bk:title> <bk:author>Matthew Mason</bk:author> </bk:book> ... </bk:books>
We have added the xmlns:{prefix} attribute to the root element. We have assigned this attribute a unique value. This unique value is usually in the form of a Uniform Resource Identifier (URI). This defines the namespace.
And, now that the namespace has been defined, we have added a bk prefix to our element names. Now, when we combine the two documents, the XML processor will see two different element names: bk:title (from the XML document) and title (from the HTML document). Note: If you have defined your tags and attributes in a DTD, you will need to update your DTD in order to make the new element names legal.
Multiple Namespaces
You could also have multiple namespaces within your XML document. For example, you could define one namespace against the root element, and another against a child element. Example:
<bk:books xmlns:bk="http://somebooksite.com/book_spec"> <bk:book> <bk:title>The Dream Saga</bk:title> <bk:author>Matthew Mason</bk:author> <pub:name xmlns:pub="http://somepublishingsite.com/spec"> Sid Harta Publishers </pub:name> <pub:email>author@sidharta.com.au</pub:email>
When you define the namespace without a prefix, all descendant elements are assumed to belong to that namespace, unless specified otherwise (i.e. with a local namespace).
XML Entities
XML entities allow you to use text to refer to a data item, instead of using the data item itself. You can use entities to represent:
y y
Characters that would otherwise cause problems for the XML processor Large blocks of data that need to be repeated throughout the document
Problematic Characters
Some characters have a special meaning in XML. For example, the less than sign (<) marks the beginning of a tag. And, of course, the greater than sign (>) marks the end of the tag. When the XML processor parses the document, it looks for these characters (and others) to determine how to interpret the document. This is fine, as long as your data doesn't contain any of these characters. But what if it does? What if your data contains say, a less than sign? Imagine you had the following text within an element: 10 < 5. When the XML processor encounters the <, it will assume it's the start of an opening tag. Problem is, it's not. In order to include characters such as < and & etc, you need to use their entity reference instead of the character itself.
Entity Syntax
You start an entity reference using the & character and close it using the ; character. Example:
<
'
'
Example
Imagine you have some text that you want to repeat at the bottom of all your documents. Let's say the text goes something like "Thank you, please come again!". Instead of typing all that text out every time you need to use it, you could create an entity called say, "footer". That way, you just need to include &footer; whenever you want to include that text. Now, if you ever need to change the text you only need to change it in one place - the definition.
<?xml version="1.0"?> <!DOCTYPE tutorials [ <!ENTITY footer "Thank you, please come again!"> <]> <tutorials> <tutorial>
<name>XML Tutorial</name> <url>http://www.quackit.com/xml/tutorial</url> <footer>&footer;</footer> </tutorial> <tutorial> <name>HTML Tutorial</name> <url>http://www.quackit.com/html/tutorial</url> <footer>&footer;</footer> </tutorial> </tutorials>
XML CDATA
In a previous lesson, we learned how to escape a single character by using an entity reference. In this lesson, we'll look at how to escape a whole block of text - not just a single character. In XML, a CDATA section is used to escape a block of text that would otherwise be parsed as markup.
CDATA Syntax
You declare a CDATA section using <![CDATA[ as the opening tag, and ]]> as the closing tag. Example:
<root> <child> <![CDATA[ Text you want to escape goes here... ]]> </child> </root>
In this example, we have a block of JavaScript code inside an XHTML document. If you've been involved in web development, you'll probably know how common JavaScript is on the web. You might also know that any block of JavaScript code could contain all sorts of potentially problematic characters. W3C has recommended that all scripts within an XHTML document be escaped using CDATA sections.
<?xml version="1.0"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Displaying the Time</title> <script type="text/javascript"> <![CDATA[ var currentTime = new Date() var hours = currentTime.getHours() var minutes = currentTime.getMinutes() var suffix = "AM"; if (hours >= 12) { suffix = "PM"; hours = hours - 12; } if (hours == 0) { hours = 12; } if (minutes < 10) minutes = "0" + minutes document.write("<b>" + hours + ":" + minutes + " " + suffix + "</b>") ]]> </script> </head> <body> <h1>Displaying the Time</h1> </body> </html>
DTD Introduction
DTD stands for Document Type Definition. A DTD allows you to create rules for the elements within your XML documents. Although XML itself has rules, the rules defined in a DTD are specific to your own needs.
So, for an XML document to be well-formed, it needs to use correct XML syntax, and it needs to conform to its DTD or schema (we'll cover XML schemas later). The DTD is declared at the top of your XML document. The actual contents of the DTD can be included within your XML document or included in another document and linked to (or both).
What's in a DTD?
A DTD consists of a list of syntax definitions for each element in your XML document. When you create a DTD, you are creating the syntax rules for any XML document that uses the DTD. You are specifying which element names can be included in the document, the attributes that each element can have, whether or not these are required or optional, and more.
Example DTD
The following example demonstrates what a DTD could look like:
<!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT <!ATTLIST tutorials (tutorial)+> tutorial (name,url)> name (#PCDATA)> url (#PCDATA)> tutorials type CDATA #REQUIRED>
I'll explain the DTD syntax a little later on, but for now, let's look at how to configure your XML document to use a DTD.
DTD <!DOCTYPE>
If you've had the opportunity to view some XML documents, you may have noticed a line starting with <!DOCTYPE appearing near the top of the document. For example, if you've viewed the source code of a (valid) XHTML file, you may have seen a line like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
The purpose of this line is to declare the Document Type Definition (DTD). Actually, we even used the DOCTYPE declaration in a previous lesson to define an entity. As mentioned in the previous lesson, a DTD specifies the rules regarding the elements within your XML document.
DOCTYPE Syntax
To use a DTD within your XML document, you need to declare it. The DTD can either be internal (written into the same document that it's being used in), or external (located in another document). You declare a DTD at the top of your XML document (in the prolog) using the <!DOCTYPE declaration. The basic syntax is:
<!DOCTYPE rootname [DTD]>
...where, rootname is the root element, and [DTD] is the actual definition. Actually, there are slight variations depending on whether your DTD is internal or external (or both), public or private. Here they are:
DOCTYPE Variation Example
y
Description This is an internal DTD (the DTD is defined between the square brackets within the XML document). The keyword SYSTEM indicates that it's a private DTD (not for public distribution). The presence of URL indicates that this is an external DTD (the DTD is defined in a document located at the URL). The keyword SYSTEM indicates
<!DOCTYPE tutorials [ <!ELEMENT tutorials (tutorial)+> <!DOCTYPE rootname <!ELEMENT tutorial (name,url)> <!ELEMENT name (#PCDATA)> [DTD]> <!ELEMENT url (#PCDATA)> <!ATTLIST tutorials type CDATA #REQUIRED> ]>
that it's a private DTD (not for public distribution). The presence of URL and [DTD] together indicates that this is both an external and internal DTD (part of the DTD is defined in a document located at the URL, the other part is defined within the XML document). The keyword PUBLIC indicates that it's a public DTD (for public distribution). The presence of URL indicates that this is an external DTD (the DTD is defined in a document located at the URL). The identifier indicates the formal public identifier and is required when using a public DTD. The keyword PUBLIC indicates that it's a public DTD (for public distribution). The presence of URL and [DTD] together indicates that this is both an external and internal DTD (part
<!DOCTYPE rootname <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" PUBLIC identifier "http://www.w3.org/TR/xhtml1/DTD/xhtml1URL> transitional.dtd">
y
<!DOCTYPE rootname PUBLIC identifier URL <!ELEMENT tutorials (tutorial)+> <!ELEMENT tutorial (name,url)> [DTD]>
<!ELEMENT name (#PCDATA)> <!ELEMENT url (#PCDATA)> <!ATTLIST tutorials type CDATA #REQUIRED> ]>
of the DTD is defined in a document located at the URL, the other part is defined within the XML document). The identifier indicates the formal public identifier and is required when using a public DTD.
The next few lessons demonstrate some of the different methods of declaring your DTD, depending on whether you're using an internal, external, or combined DTD.
Internal DTD
Whether you use an external or internal DTD, the actual syntax for the DTD is the same - the same code could just as easily be part of an internal DTD or an external one. The only difference between internal and external is in the way it's declared with DOCTYPE. Using an internal DTD, the code is placed between the DOCTYPE tags (i.e. <!DOCTYPE
tutorials [ and ]>.
</tutorial> </tutorials>
External DTD
An external DTD is one that resides in a separate document. To use the DTD, you need to link to it from your XML document by providing the URI of the DTD file. This URI is typically in the form of a URL. The URL can point to a local file using a relative reference, or a remote one (i.e. using HTTP) using an absolute reference.
And, using the above XML document as an example, here's an example of what "tutorials.dtd" (the external DTD file) could look like. Note that the external DTD file doesn't need the DOCTYPE declaration - it is already on the XML file that is using this DTD:
<!ELEMENT <!ELEMENT <!ELEMENT <!ELEMENT <!ATTLIST tutorials (tutorial)+> tutorial (name,url)> name (#PCDATA)> url (#PCDATA)> tutorials type CDATA #REQUIRED>
Combined DTD
You can use both an internal DTD and an external one at the same time. This could be useful if you need to adhere to a common DTD, but also need to define your own definitions locally.
Example
This is an example of using both an external DTD and an internal one for the same XML document. The external DTD resides in "tutorials.dtd" and is called first in the DOCTYPE
declaration. The internal DTD follows the external one but still resides within the DOCTYPE declaration: Here, I've added a new element called "summary". This element must be present under the "tutorial" element. Because this element hasn't been defined in the external DTD, I need to define it internally. Once again, we're setting the "standalone" attribute to "no" because we rely on an external resource.
<?xml version="1.0" standalone="no"?> <!DOCTYPE tutorials SYSTEM "tutorials.dtd" [ <!ELEMENT tutorial (summary)> <!ELEMENT summary (#PCDATA)> ]> <tutorials> <tutorial> <name>XML Tutorial</name> <url>http://www.quackit.com/xml/tutorial</url> <summary>Best XML tutorial on the web!</summary> </tutorial> <tutorial> <name>HTML Tutorial</name> <url>http://www.quackit.com/html/tutorial</url> <summary>Best HTML tutorial on the web!</summary> </tutorial> </tutorials>
FPI Syntax
An FPI is made up of 4 fields, each separated by double forward slashes (//):
field 1//field 2//field 3//field 4
FPI Example
Here's a real life example of an FPI. In this case, the DTD was created by the W3C for XHTML:
-//W3C//DTD XHTML 1.0 Transitional//EN
FPI Fields
An FPI must contain the following fields:
Field Separator //
Example
Description This is used to separate the different fields of the FPI. Indicates whether the DTD is connected to a formal standard or not. If the DTD hasn't been approved (for example, you've defined the DTD yourself), use a hypen (-). If the DTD has been approved by a nonstandards body, use a plus sign "+". If the DTD has been approved by a formal standards body this field should be a reference to the standard itself. Holds the name of the group (or person) responsible for the DTD. The above example is maintained by the W3C, so "W3C" appears in the second field. Indicates the type of document that is being described. This usually contains some form of unique identifier (such as a version number). Specifies the language that the DTD uses. This is achieved by using the two letter identifier for the language (i.e. for english, use "EN").
First field -
Second field
W3C
DTD Elements
Creating a DTD is quite straight forward. It's really just a matter of defining your elements, attributes, and/or entities. Over the next few lessons, I'll explain how to define your elements, attributes, and entities. In this lesson, we'll look at the syntax for defining your XML elements.
To define an element in your DTD, you use the <!ELEMENT> declaration. The actual contents of your <!ELEMENT> declaration will depend on the syntax rules you need to apply to your element.
Basic Syntax
The <!ELEMENT> declaration has the following syntax:
<!ELEMENT element_name content_model>
Here, element_name is the name of the element you're defining. The content model could indicate a specific rule, data or another element.
y y
If it specifies a rule, it will be set to either ANY or EMPTY. If specifies data or another element, the data type/element name needs to be surrounded by brackets (i.e. (tutorial) or (#PCDATA)).
The following examples show you how to use this syntax for defining your elements.
Plain Text
If an element should contain plain text, you define the element using #PCDATA. PCDATA stands for Parsed Character Data and is the way you specify non-markup text in your DTDs. Using this example - <name>XML Tutorial</name> - the "XML Tutorial" part is the PCDATA. The other part consists of markup. Syntax:
<!ELEMENT element_name (#PCDATA)>
Example:
<!ELEMENT name (#PCDATA)>
The above line in your DTD allows the "name" element to contain non-markup data in your XML document:
<name>XML Tutorial</name>
Unrestricted Elements
If it doesn't matter what your element contains, you can create an element using the content_model of ANY. Note that doing this removes all syntax checking, so you should avoid using this if possible. You're better off defining a specific content model.
Syntax:
<!ELEMENT element_name ANY>
Example:
<!ELEMENT tutorials ANY>
Empty Elements
You might remember that an empty element is one without a closing tag. For example, in XHTML, the <br /> and <img /> tags are empty elements. Here's how you define an empty element: Syntax:
<!ELEMENT element_name EMPTY>
Example:
<!ELEMENT header EMPTY>
The above line in your DTD defines the following empty element for your XML document:
<header />
Child Elements
You can specify that an element must contain another element, by providing the name of the element it must contain. Here's how you do that: Syntax:
<!ELEMENT element_name (child_element_name)>
Example:
<!ELEMENT tutorials (tutorial)>
The above line in your DTD allows the "tutorials" element to contain one instance of the "tutorial" element in your XML document:
<tutorials> <tutorial></tutorial> </tutorials>
Example:
<!ELEMENT tutorial (name, url)>
The above line in your DTD allows the "tutorial" element to contain one instance of the "name" element and one instance of the "url" element in your XML document:
<tutorials> <tutorial> <name></name> <url></url> </tutorial> </tutorials>
| ()
a|b (expression)
a followed by b An expression surrounded by parentheses is treated as a unit and could have any one of the following suffixes ?, *, or +.
Zero or More
To allow zero or more of the same child element, use an asterisk (*): Syntax:
<!ELEMENT element_name (child_element_name*)>
Example:
<!ELEMENT tutorials (tutorial*)>
One or More
To allow one or more of the same child element, use a plus sign (+): Syntax:
<!ELEMENT element_name (child_element_name+)>
Example:
<!ELEMENT tutorials (tutorial+)>
Zero or One
To allow either zero or one of the same child element, use a question mark (?): Syntax:
<!ELEMENT element_name (child_element_name?)>
Example:
<!ELEMENT tutorials (tutorial?)>
Choices
You can define a choice between one or another element by using the pipe (|) operator. For example, if the "tutorial" element requires a child called either "name", "title", or "subject" (but only one of these), you can do the following: Syntax:
<!ELEMENT element_name (choice_1 | choice_2 | choice_3)>
Example:
<!ELEMENT tutorial (name | title | subject)>
Mixed Content
You can use the pipe (|) operator to specify that an element can contain both PCDATA and other elements: Syntax:
<!ELEMENT element_name (#PCDATA | child_element_name)>
Example:
<!ELEMENT tutorial (#PCDATA | name | title | subject)*>
Example:
<!ELEMENT tutorial (name+, url?)>
The above example allows the "tutorial" element to contain one or more instance of the "name" element, and zero or one instance of the "url" element.
Subsequences
You can use parentheses to create a subsequence (i.e. a sequence within a sequence). This enables you to apply DTD operators to a subsequence:
Syntax:
<!ELEMENT element_name ((sequence) dtd_operator sequence)>
Example:
<!ELEMENT tutorial ((author,rating?)+ name, url*)>
The above example specifies that the "tutorial" element can contain one or more "author" elements, with each occurence having an optional "rating" element.
DTD Attributes
Just as you need to define all elements in your DTD, you also need to define any attributes they use. You use the <!ATTLIST> declaration to define attributes in your DTD.
Syntax
You use a single <!ATTLIST> declaration to declare all attributes for a given element. In other words, for each element (that contains attributes), you only need one <!ATTLIST> declaration. The <!ATTLIST> declaration has the following syntax:
<!ATTLIST element_name attribute_name TYPE DEFAULT_VALUE attribute_name TYPE DEFAULT_VALUE attribute_name TYPE DEFAULT_VALUE ...>
Here, element_name refers to the element that you're defining attributes for, attribute_name is the name of the attribute that you're declaring, TYPE is the attribute type, and DEFAULT_VALUE is it's default value.
Example
<!ATTLIST tutorial published CDATA "No">
Here, we are defining an attribute called "published" for the "tutorial" element. The attribute's type is CDATA and it's default value is "No".
Default Values
The attribute TYPE field can be set to one of the following values:
Value value #IMPLIED A simple text value, enclosed in quotes. Specifies that there is no default value for this attribute, and that the attribute is optional. Description
#REQUIRED There is no default value for this attribute, but a a value must be assigned. #FIXED value The #FIXED part specifies that the value must be the value provided. The value part represents the actual value.
value
You can provide an actual value to be the default value by placing it in quotes. Syntax:
<!ATTLIST element_name attribute_name CDATA "default_value">
Example:
<!ATTLIST tutorial published CDATA "No">
#REQUIRED
The #REQUIRED keyword specifies that you won't be providing a default value, but that you require that anyone using this DTD does provide one. Syntax:
<!ATTLIST element_name attribute_name CDATA #REQUIRED>
Example:
<!ATTLIST tutorial published CDATA #REQUIRED>
#IMPLIED
The #IMPLIED keyword specifies that you won't be providing a default value, and that the attribute is optional for users of this DTD. Syntax:
<!ATTLIST element_name attribute_name CDATA #IMPLIED>
Example:
<!ATTLIST tutorial rating CDATA #IMPLIED>
#FIXED
The #FIXED keyword specifies that you will provide value, and that's the only value that can be used by users of this DTD. Syntax:
<!ATTLIST element_name attribute_name CDATA #FIXED "value">
Example:
<!ATTLIST tutorial language CDATA #FIXED "EN">
ENTITY ENTITIES
The name of an entity (which must be declared in the DTD) A list of entity names, separated by whitespaces. (All entities must be declared in the DTD)
Enumerated A list of values. The value of the attribute must be one from this list. ID IDREF IDREFS A unique ID or name. Must be a valid XML name. Represents the value of an ID attribute of another element. Represents multiple IDs of elements, separated by whitespace.
NMTOKEN A valid XML name. NMTOKENS A list of valid XML names, separated by whitespace. NOTATION A notation name (which must be declared in the DTD).
Syntax
The <!ENTITY> declaration for general entities has the following syntax:
<!ENTITY name definition>
You can also declare external general entities. This enables you to use an entity from a remote file. You declare external general entities using the following syntax: Private:
<!ENTITY name SYSTEM uri>
Public:
<!ENTITY name PUBLIC FPI uri>
Example
<!ENTITY author "Homer Flinstone">
After declaring the entity named "author", we can now use it in our XML document:
<books> <book> <name>Life as a cartoon character</name> <author>&author;</author> </book> </book>
Syntax
When creating a parameter entity, you need to insert a percentage sign (%) between ENTITY, and the name of the entity:
<!ENTITY % name definition>
You can also declare external parameter entities. You do this using the following syntax: Private:
<!ENTITY % name SYSTEM uri>
Public:
<!ENTITY % name PUBLIC FPI uri>
Example
Here's an example of an internal parameter entity. In this example, the second line is the actual declaration for the "author" element. This is quite a simplistic example. In reality, you would use parameter entities to represent text that you need to repeat many times within your DTD. For example, multiple elements might share the same text in their declarations. In this case, a parameter reference could be used instead of repeating the same text.
Syntax
<!ENTITY name SYSTEM value NDATA TYPE>
You can also use public external unparsed entities by using the PUBLIC keyword along with a Formal Public Identifier (FPI):
<!ENTITY name PUBLIC FPI value NDATA TYPE>
Example
Here's an example of a private external unparsed entity. Here, we declare a new notation named "JPG" for the "image/jpeg" MIME type. Then we declare an external unparsed entity called "mt_cook_1" that refers to an image file called "mt_cook1_jpg". We then create a new attribute of type ENTITY - this means that we can now use this attribute in our XML document to refer to the unparsed external entity.
<!NOTATION JPG SYSTEM "image/jpeg"> <!ENTITY mt_cook_1 SYSTEM "mt_cook1.jpg" NDATA JPG> <!ATTLIST mountain photo ENTITY #IMPLIED>
After declaring the external unparsed entity in our DTD (and creating an attribute of type ENTITY), we can now embed it in our XML document:
<mountains> <mountain photo="mt_cook_1"> <name>Mount Cook</name> </mountain> <mountain> <name>Cradle Mountain</name> </mountain> </mountains>
If you need to embed multiple external unparsed entities via a single attribute, you simply give your attribute a type of ENTITIES (plural). This allows you to assign multiple images separated by a space. Here's an example:
<!NOTATION JPG SYSTEM "image/jpeg"> <!ENTITY mt_cook_1 SYSTEM "mt_cook1.jpg" NDATA JPG> <!ENTITY mt_cook_2 SYSTEM "mt_cook2.jpg" NDATA JPG> <!ATTLIST mountain photo ENTITIES #IMPLIED>
Now that we've changed the "photo" attribute to type ENTITIES, we can assign multiple images to it in our XML document:
<mountains> <mountain photo="mt_cook_1 mt_cook_2"> <name>Mount Cook</name> </mountain> <mountain> <name>Cradle Mountain</name> </mountain> </mountains>
XSLT Introduction
You might remember from a previous lesson that we can use a language called Extensible Styles Language XSL to format our XML documents. XSL actually comes in two parts - a transformation language (XSLT) and a formatting language using formatting objects. This section of the XML tutorial covers XSLT. XSLT, which stands for Extensible Styles Language Transformations, enables you to transform XML documents into another form. For example, you can take your XML document, combine it with HTML/CSS, and it will look completely different when viewing it in your user agent/browser.
XSLT Documents
An XSLT document is a valid XML document. An XSLT document consists of a number of elements/tags/attributes. These can be XSL elements or elements from another language (such as HTML). When you look at an XSLT document, you will notice that it is constructed like any other XML document.
Processing a Transformation
A transformation can take place in one of three locations:
y y y
On the server On the client (for example, your web browser) With a standalone program
The examples in this tutorial will use the client for transforming the XML documents.
XSLT Example
Here's an example of an XML document that has been transformed using XSLT.
Before...
We can take a raw XML file that looks something like this:
After...
...and apply XSLT so that it looks something like this:
You might have noticed that the "After" shot contains more than the raw XML file. It contains a heading ("Cool Tutorials") and some text ("Hey, check out these tutorials!"). This is one of the benefits of XSLT. The following lessons explain XSLT in more detail, and demonstrate how to apply XSLT to an XML document.
How to Do This?
Instead of linking to a CSS file (as we did in the XML with CSS lesson), this time we link to a XSL file. Step 1 (XML file): Create an XML file with the following content and save it.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml-stylesheet type="text/xsl" href="tutorials.xsl"?> <tutorials> <tutorial> <name>XML Tutorial</name> <url>http://www.quackit.com/xml/tutorial</url> </tutorial> <tutorial> <name>HTML Tutorial</name> <url>http://www.quackit.com/html/tutorial</url> </tutorial> </tutorials>
Step 2 (XSL file): Create a file with the following content and save it as tutorials.xsl into the same directory as the XML file.
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html> <head> <title>XML XSL Example</title> <style type="text/css"> body { margin:10px; background-color:#ccff00; font-family:verdana,helvetica,sans-serif; } .tutorial-name { display:block; font-weight:bold; } .tutorial-url { display:block; color:#636363; font-size:small; font-style:italic; } </style> </head> <body> <h2>Cool Tutorials</h2> <p>Hey, check out these tutorials!</p> <xsl:apply-templates/> </body> </html> </xsl:template> <xsl:template match="tutorial"> <span class="tutorial-name"><xsl:value-of select="name"/></span> <span class="tutorial-url"><xsl:value-of select="url"/></span> </xsl:template> </xsl:stylesheet>
This XSL file contains XSL markup, HTML markup, and CSS. The following lessons explain XSLT in more detail, and demonstrate how to apply XSLT to an XML document.
XSLT Syntax
All XSLT documents need to be well-formed and valid XML documents, so you need to follow the same syntax rules that apply to any other XML document.
As well as ensuring that your XSLT documents are valid XML, you need to ensure they are valid XSLT documents. Here's what you need to remember when creating XSLT documents.
XML Version
XSL documents are also XML documents and so we should include the XML version in the document's prolog. We should also set the standalone attribute to "no" as we now rely on an external resource (i.e. the external XSL file).
<?xml version="1.0" standalone="no"?>
Example:
<xsl:template match="/"> .... </xsl:template>
Example
In this case, I'm selecting the root node (i.e. tutorials). By selecting this node, the template element tells the XSLT processor how to transform the output. What I'm doing here is telling the processor to replace the root node (i.e. the whole XML document) with what I've written between the <xsl:template> tags. In this case, I have written the contents of an HTML document inside the <xsl:template> tags. When a user views any XML document that uses this XSL document, they will simply see the line "New content..." and the browser's title bar will read "My XSLT Example".
<xsl:template match="tutorials"> <html> <head> <title>My XSLT Example</title> </head> <body> <p>New content...</p> </body> </html> </xsl:template>
The XSLT <xsl:apply-templates/> element allows us to determine where the content of its children appear on our transformed document.
Usage Example
Here, we are using two <xsl:template> elements; one for the root node, and one for its children. We have placed the <xsl:apply-templates/> element within the <xsl:template> element for the root node. Doing this applies the results of our other <xsl:template> element.
<xsl:template match="/"> (other content/HTML markup goes here) <xsl:apply-templates/> </xsl:template> <xsl:template match="child"> (other content/XSLT/HTML markup goes here) </xsl:template>
So, by doing this, we can use other XSLT elements to retrieve data from the child elements, and pass it to the main template for display. In particular, the XSLT <xsl:value-of/> element is useful for retrieving data from an XML element. We'll look at that element next.
Usage Example
This example is a continuation of the example from the previous lesson. Here, we have added the <xsl:value-of/> element to extract data from the child nodes called "name" and "url".
<xsl:template match="/"> (other content/HTML markup goes here) <xsl:apply-templates/> </xsl:template> <xsl:template match="tutorial"> <xsl:value-of select="name"/> <xsl:value-of select="url"/> </xsl:template>
So, let's have another look at our XML document, and see which values will be selected:
<?xml version="1.0" standalone="no"?> <?xml-stylesheet type="text/xsl" href="tutorials.xsl"?> <tutorials> <tutorial> <name>XML Tutorial</name> <url>http://www.quackit.com/xml/tutorial</url> </tutorial> <tutorial> <name>HTML Tutorial</name> <url>http://www.quackit.com/html/tutorial</url> </tutorial> </tutorials>
And just to refresh your memory, these values will be displayed where we choose to place the XSLT <xsl:apply-templates> element.
To extract data from both "name" elements, we can use <xsl:for-each> in conjunction with <xsl:value-of>.
<xsl:for-each> Example
Here, we use <xsl:for-each> to loop through each "name" element, and <xsl:value-of> to extract data from each node.
Note the value of the select attribute ("."). This expression specifies the current node. The <xsl:element name="br"/> element/attribute is there simply for readibility purposes - it provides a line break after each iteration.
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="tutorial"> <xsl:for-each select="name"> <xsl:value-of select="."/><xsl:element name="br"/> </xsl:for-each> </xsl:template> </xsl:stylesheet>
<xsl:sort> Example
Here, we use <xsl:for-each> to loop through each "tutorial" element, and <xsl:sort> to sort by the "name" node. We then use the <xsl:value-of> to extract data from the "name" node.
<?xml version="1.0" standalone="no"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="tutorials"> <xsl:for-each select="tutorial"> <xsl:sort select="name"/> <xsl:value-of select="name"/><xsl:element name="br"/> </xsl:for-each> </xsl:template> </xsl:stylesheet>
Result
So, let's see what would happen if we applied the above XSLT document to the following XML document:
<tutorials> <tutorial> <name>XML Tutorial</name> <url>http://www.quackit.com/xml/tutorial</url> </tutorial> <tutorial> <name>HTML Tutorial</name> <url>http://www.quackit.com/html/tutorial</url> </tutorial> </tutorials>
Before:
This is how the contents would be displayed before applying the <xsl:sort> element:
XML Tutorial HTML Tutorial
After:
This is how the contents would be displayed after applying the <xsl:sort> element:
HTML Tutorial XML Tutorial
<xsl:if> Example
The Source File
Imagine have an XML file containing a list of food and it's nutritional value. Something like this:
<?xml version="1.0"?> <food_list> <food_item type="vegetable"> <name>Agar</name> <carbs_per_serving>81</carbs_per_serving> <fiber_per_serving>8</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>1280</kj_per_serving>
</food_item> <food_item type="vegetable"> <name>Asparagus</name> <carbs_per_serving>1</carbs_per_serving> <fiber_per_serving>1</fiber_per_serving> <fat_per_serving>0</fat_per_serving> <kj_per_serving>40</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Cabbage</name> <carbs_per_serving>0</carbs_per_serving> <fiber_per_serving>1</fiber_per_serving> <fat_per_serving>0</fat_per_serving> <kj_per_serving>14</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Potato</name> <carbs_per_serving>21.5</carbs_per_serving> <fiber_per_serving>2</fiber_per_serving> <fat_per_serving>1</fat_per_serving> <kj_per_serving>460</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Pumpkin</name> <carbs_per_serving>6</carbs_per_serving> <fiber_per_serving>1</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>150</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Yam</name> <carbs_per_serving>30.5</carbs_per_serving> <fiber_per_serving>2</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>550</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Zucchini</name> <carbs_per_serving>1.5</carbs_per_serving> <fiber_per_serving>1.5</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>55</kj_per_serving> </food_item> <food_item type="seafood"> <name>Abalone</name> <carbs_per_serving>0</carbs_per_serving> <fiber_per_serving>0</fiber_per_serving> <fat_per_serving>1</fat_per_serving> <kj_per_serving>400</kj_per_serving> </food_item> <food_item type="seafood"> <name>Barramundi</name> <carbs_per_serving>0</carbs_per_serving> <fiber_per_serving>0</fiber_per_serving> <fat_per_serving>2</fat_per_serving> <kj_per_serving>390</kj_per_serving> </food_item>
<food_item type="fruit"> <name>Apple</name> <carbs_per_serving>15</carbs_per_serving> <fiber_per_serving>2.5</fiber_per_serving> <fat_per_serving>0</fat_per_serving> <kj_per_serving>250</kj_per_serving> </food_item> <food_item type="fruit"> <name>Kiwi Fruit</name> <carbs_per_serving>7.5</carbs_per_serving> <fiber_per_serving>2.5</fiber_per_serving> <fat_per_serving>0</fat_per_serving> <kj_per_serving>150</kj_per_serving> </food_item> <food_item type="grain"> <name>Oatbran</name> <carbs_per_serving>62</carbs_per_serving> <fiber_per_serving>14</fiber_per_serving> <fat_per_serving>7</fat_per_serving> <kj_per_serving>1400</kj_per_serving> </food_item> <food_item type="grain"> <name>Wheatgerm</name> <carbs_per_serving>1.5</carbs_per_serving> <fiber_per_serving>1</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>70</kj_per_serving> </food_item> </food_list>
The Requirement
Now, imagine we're only interested in the vegetables - we only want to display the food that have a type attribute of "vegetable". And, we also want to display it nicely formatted in an HTML table. Something like this:
The Solution
To achieve the above outcome, we use <xsl:for-each> to loop through each "food_item" element, and <xsl:if> to check the value of the "type" attribute (we do this by using the @ symbol - that's how you specify an attribute). If the attribute value equals "vegetable" we output the details.
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="food_list"> <table> <tr style="background-color:#ccff00"> <th>Food Item</th> <th>Carbs (g)</th> <th>Fiber (g)</th> <th>Fat (g)</th> <th>Energy (kj)</th> </tr> <xsl:for-each select="food_item"> <xsl:if test="@type = 'vegetable'"> <tr style="background-color:#00cc00"> <td><xsl:value-of select="name"/></td> <td><xsl:value-of select="carbs_per_serving"/></td>
<td><xsl:value-of select="fiber_per_serving"/></td> <td><xsl:value-of select="fat_per_serving"/></td> <td><xsl:value-of select="kj_per_serving"/></td> </tr> </xsl:if> </xsl:for-each> </table> </xsl:template> </xsl:stylesheet>
<xsl:choose> Example
The Source File
Imagine we have an XML file containing different food items and their nutritional value - like this:
<?xml version="1.0"?> <food_list> <food_item type="vegetable"> <name>Agar</name> <carbs_per_serving>81</carbs_per_serving> <fiber_per_serving>8</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>1280</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Asparagus</name> <carbs_per_serving>1</carbs_per_serving> <fiber_per_serving>1</fiber_per_serving> <fat_per_serving>0</fat_per_serving> <kj_per_serving>40</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Cabbage</name> <carbs_per_serving>0</carbs_per_serving> <fiber_per_serving>1</fiber_per_serving> <fat_per_serving>0</fat_per_serving> <kj_per_serving>14</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Potato</name>
<carbs_per_serving>21.5</carbs_per_serving> <fiber_per_serving>2</fiber_per_serving> <fat_per_serving>1</fat_per_serving> <kj_per_serving>460</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Pumpkin</name> <carbs_per_serving>6</carbs_per_serving> <fiber_per_serving>1</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>150</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Yam</name> <carbs_per_serving>30.5</carbs_per_serving> <fiber_per_serving>2</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>550</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Zucchini</name> <carbs_per_serving>1.5</carbs_per_serving> <fiber_per_serving>1.5</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>55</kj_per_serving> </food_item> <food_item type="seafood"> <name>Abalone</name> <carbs_per_serving>0</carbs_per_serving> <fiber_per_serving>0</fiber_per_serving> <fat_per_serving>1</fat_per_serving> <kj_per_serving>400</kj_per_serving> </food_item> <food_item type="seafood"> <name>Barramundi</name> <carbs_per_serving>0</carbs_per_serving> <fiber_per_serving>0</fiber_per_serving> <fat_per_serving>2</fat_per_serving> <kj_per_serving>390</kj_per_serving> </food_item> <food_item type="fruit"> <name>Apple</name> <carbs_per_serving>15</carbs_per_serving> <fiber_per_serving>2.5</fiber_per_serving> <fat_per_serving>0</fat_per_serving> <kj_per_serving>250</kj_per_serving> </food_item> <food_item type="fruit"> <name>Kiwi Fruit</name> <carbs_per_serving>7.5</carbs_per_serving> <fiber_per_serving>2.5</fiber_per_serving> <fat_per_serving>0</fat_per_serving> <kj_per_serving>150</kj_per_serving> </food_item> <food_item type="grain"> <name>Oatbran</name> <carbs_per_serving>62</carbs_per_serving>
<fiber_per_serving>14</fiber_per_serving> <fat_per_serving>7</fat_per_serving> <kj_per_serving>1400</kj_per_serving> </food_item> <food_item type="grain"> <name>Wheatgerm</name> <carbs_per_serving>1.5</carbs_per_serving> <fiber_per_serving>1</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>70</kj_per_serving> </food_item> </food_list>
The Requirement
Now, imagine if we want to present the contents of our XML file in a table and highlight the rows a different color depending on the type of food it is - something like this:
The Solution
We could do this using the following XSL file. In this file, we are checking the type attribute of the <food_item> element. We can find the value of the attribute by typing it's name with a @. If the value is "grain" we specify one color. If it's "vegetable" we specify another. If it's neither of these, we specify a default color using <xsl:otherwise>.
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="food_list"> <table> <tr style="background-color:#ccff00"> <th>Food Item</th> <th>Carbs (g)</th> <th>Fiber (g)</th> <th>Fat (g)</th> <th>Energy (kj)</th> </tr> <xsl:for-each select="food_item"> <xsl:choose> <xsl:when test="@type = 'grain'"> <tr style="background-color:#cccc00"> <td><xsl:value-of select="name"/></td> <td><xsl:value-of select="carbs_per_serving"/></td> <td><xsl:value-of select="fiber_per_serving"/></td> <td><xsl:value-of select="fat_per_serving"/></td> <td><xsl:value-of select="kj_per_serving"/></td> </tr> </xsl:when> <xsl:when test="@type = 'vegetable'"> <tr style="background-color:#00cc00"> <td><xsl:value-of select="name"/></td> <td><xsl:value-of select="carbs_per_serving"/></td> <td><xsl:value-of select="fiber_per_serving"/></td> <td><xsl:value-of select="fat_per_serving"/></td> <td><xsl:value-of select="kj_per_serving"/></td> </tr> </xsl:when> <xsl:otherwise> <tr style="background-color:#cccccc"> <td><xsl:value-of select="name"/></td> <td><xsl:value-of select="carbs_per_serving"/></td> <td><xsl:value-of select="fiber_per_serving"/></td> <td><xsl:value-of select="fat_per_serving"/></td> <td><xsl:value-of select="kj_per_serving"/></td> </tr> </xsl:otherwise> </xsl:choose> </xsl:for-each> </table> </xsl:template>
</xsl:stylesheet>
XPath Introduction
XPath is a language that enables you to navigate, and find data, within your XML documents. Using XPath, you can select one or more nodes in order to retrieve the data they contain. Actually, we've already used XPath in this XML tutorial - we used it to program some of our XSL transformations. XPath is used quite extensively with XSLT. Once you start learning XPath, you'll see how suited it is to XSLT.
XPath Purpose
Since XPath is used for finding data within XML documents, this enables you to write applications that make use of the data within an XML document. In fact, in order to use XSLT (to transform the contents of your XML documents), you need to use XPath. Other XML based languages such as XQuery and XPointer also rely on XPath expressions, so XPath really does play an important role when writing XML applications. Consider the following XML document:
<albums> <rock> <title>Machine Head</title> <artist>Deep Purple</artist> </rock> <blues> <title>Greens From The Garden</title> <artist>Cory Harris</artist> </blues> <country> <title>The Ranch</title> <artist>The Ranch</artist> </country> </albums>
What are some of the things we might be interested in when writing an application? We might need to extract the title of all albums for example. Or, we might only be interested in the artists. Or, we might only be interested in albums and artists from a specific niche, such as rock. XPath allows us to select only the nodes we're interested in.
The above expression could be applied against the following XML document:
<albums> <rock> <title>Machine Head</title> <artist>Deep Purple</artist> </rock> <blues> <title>Greens From The Garden</title> <artist>Cory Harris</artist> </blues> <country> <title>The Ranch</title> <artist>The Ranch</artist> </country> </albums>
Another Example
If we wanted to select the artist instead, we would use this location path:
albums/rock/artist
<artist>Cory Harris</artist> </blues> <country> <title>The Ranch</title> <artist>The Ranch</artist> </country> </albums>
<title>Machine Head</title> <artist>Deep Purple</artist> </rock> <blues> <title>Greens From The Garden</title> <artist>Cory Harris</artist> </blues> <country> <title>The Ranch</title> <artist>The Ranch</artist> </country> </albums>
If we wanted to select the "title" node of all albums, we could use the following (absolute) location paths:
albums/rock/title albums/blues/title albums/country/title
The Result
Here are the nodes that are selected using the above location path.
<albums> <rock> <title>Machine Head</title> <artist>Deep Purple</artist> </rock> <blues> <title>Greens From The Garden</title> <artist>Cory Harris</artist> </blues> <country> <title>The Ranch</title> <artist>The Ranch</artist> </country> </albums>
If we wanted to select the "title" node of all albums, we could use the following (relative) location path:
title
The Result
This single line of code has exactly the same result as the example in the previous lesson. The only difference is that, in the previous lesson, we needed 3 lines of code to provide the same result. So to just to make sure you understand what this line of code is doing, it is selecting all title nodes within our XML document. We don't need to provide the full path - just the name of the node we need to work with. This makes our like easier and keeps our code nice and clean.
<albums> <rock> <title>Machine Head</title> <artist>Deep Purple</artist> </rock> <blues> <title>Greens From The Garden</title>
<artist>Cory Harris</artist> </blues> <country> <title>The Ranch</title> <artist>The Ranch</artist> </country> </albums>
Children
We can also select a node's children using relative location paths. Example 1 - Selecting the two children of the "rock" node ("title" and "artist"). The context node is "rock", because that's where our relative path starts:
rock/title rock/artist
Example 2 - Using a wildcard to select all children of the "rock" node. This (single line of code) has the same result as the above two lines of code. Further, if another node was added to the XML document under the "rock" node, it would be automatically included using the wildcard:
rock/*
XPath Attributes
To select an attribute using XPath, you prefix the attribute's name with a @ symbol.
<artist status="active">Deep Purple</artist> </rock> <blues> <title>Greens From The Garden</title> <artist status="active">Cory Harris</artist> </blues> <country> <title>The Ranch</title> <artist status="disbanded">The Ranch</artist> </country> </albums>
If we wanted to select the "status" attribute of the "artist" node under the "rock" node, we could use the following expression:
albums/rock/artist/@status
Another Example
Attributes, just like any other node, can be the subject of a conditional statement. For example, imagine we're using XSLT to transform our XML document, and we want to select all "artist" nodes where the "status" attribute is set to "active". We could use the XSL "if" element to test the value. Here's what we would write:
<xsl:if test="@status = 'active'"> (content goes here) </xsl:if>
XPath Axis
You'll remember from the lesson on location paths that each location path is made up of location steps. Location steps can also include an axis. In this lesson, we'll look at XPath axes (plural for axis).
What is an Axis?
An axis stores certain information about the context node or other nodes within the document. The information it stores depends on the axis being used. For example, an axis called "child" stores information about the children of the context node. Therefore, we could use this axis to select a child from the context node.
Syntax
You use an axis by using it's name, along with a node test, and optionally, one or more predicates. The axis and node test are separated by ::, and the predicate/s are enclosed in []. Axis without predicates - Here's the syntax you use if you don't have any predicates:
axis::node_test
Axis with predicates - Here's the syntax you use if you have one or more predicates:
axis::node_test[predicate/s]
Axis Usage
Up until now, our location steps have specified the exact nodes in the path, or they have used a wildcard to specify unknown nodes. For example, they have been constructed something like this:
node1/node2/*
We have other options when building our XPath expressions - we could use an axis. Consider the following expression:
child::title
This expression looks a little different to the ones we've looked at so far. The expression is selecting a node called "title", but only when it's a child of the context node (remember that context node refers to the current node). You might be thinking, "Yeah that's fine, but how do I know what the context node is?"
Example
Here's an example of how we could use the axis mentioned above:
<xsl:template match="book"> <xsl:value-of select="child::title"/> </xsl:template>
You'll remember from our XSLT lessons that this statement is selecting the value from a node within the "book" context. We know we're in the "book" context because of the match="book" (which is selecting a node called "book"). Therefore, we can explicitly state that we want to select the "title" node which is a child of the context node.
List of Axes
There are many other axes you can use within your XPath expressions. Here's a list of the axes you can use with XPath:
Axis ancestor ancestor-orself attribute child descendant Description Contains the ancestors of the context node. Ancestors include the parent, and it's parent, and it's parent etc all the way back up to the root node. Contains the context node and it's ancestors. Contains the attributes of the context node. Contains the children of the context node. Contains the descendants of the context node. Descendants include the node's children, and that child's children, and it's children etc (until there are no more children)
descendant-orContains the context node and it's descendants. self following followingsibling namespace parent preceding self Contains all nodes that come after the context node (i.e. after it's closing tag). Contains the following siblings of the context node. Siblings are at the same level as the context node and share it's parent. Contains the namespace of the context node. Contains the parent of the context node. Contains all nodes that come before the context node (i.e. before it's opening tag). Contains the context node.
To refresh our memory, a node test is part of an expression to retrieve one or more nodes. Here's where a node test goes within our expression:
axis::node_test
If you have one or more predicates, your node test comes before the predicate/s:
axis::node_test[predicate/s]
XPath Predicate
In our XPath expressions, we've learned that a location path consists of an axis, a node test, and optionally, one or more predicates. We've covered axes and node tests. Now let's look at predicates.
Predicate Syntax
Here's where an XPath goes within our expression (in case you've forgotten!):
axis::node_test[predicate/s]
Predicate Example
In the following example, we're using the XSL "value-of" element to select a node. The "select" attribute of this element specifies an XPath expression. In the expression, [@status = 'active'] is the predicate. In this case, the predicate is being used to narrow the selection down to only those records that have their "status" attribute set to "active":
<xsl:value-of select="child::artist[@status = 'active']"/>
Returns the total number of nodes in the node set as provided between the parentheses. If you leave the parentheses blank, it will use the context node.
id((string1, string2, Returns the nodes whose ID matches the string/s passed to the function. ...) node) localname(node_set) namespaceuri(node_set) name(node_set) Returns the local name of the first node in the node set. The local name is the name without the namespace prefix. To use the context node, simply leave node_set blank. Returns the URI of the namespace of the first node in the node set. To use the context node, leave node_set blank. Returns the full, qualified name of the first node in the node set. To use the context node, simply leave node_set blank.
<fat_per_serving>1</fat_per_serving> <kj_per_serving>460</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Pumpkin</name> <carbs_per_serving>6</carbs_per_serving> <fiber_per_serving>1</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>150</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Yam</name> <carbs_per_serving>30.5</carbs_per_serving> <fiber_per_serving>2</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>550</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Zucchini</name> <carbs_per_serving>1.5</carbs_per_serving> <fiber_per_serving>1.5</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>55</kj_per_serving> </food_item> <food_item type="seafood"> <name>Abalone</name> <carbs_per_serving>0</carbs_per_serving> <fiber_per_serving>0</fiber_per_serving> <fat_per_serving>1</fat_per_serving> <kj_per_serving>400</kj_per_serving> </food_item> <food_item type="seafood"> <name>Barramundi</name> <carbs_per_serving>0</carbs_per_serving> <fiber_per_serving>0</fiber_per_serving> <fat_per_serving>2</fat_per_serving> <kj_per_serving>390</kj_per_serving> </food_item> <food_item type="fruit"> <name>Apple</name> <carbs_per_serving>15</carbs_per_serving> <fiber_per_serving>2.5</fiber_per_serving> <fat_per_serving>0</fat_per_serving> <kj_per_serving>250</kj_per_serving> </food_item> <food_item type="fruit"> <name>Kiwi Fruit</name> <carbs_per_serving>7.5</carbs_per_serving> <fiber_per_serving>2.5</fiber_per_serving> <fat_per_serving>0</fat_per_serving> <kj_per_serving>150</kj_per_serving> </food_item> <food_item type="grain"> <name>Oatbran</name> <carbs_per_serving>62</carbs_per_serving> <fiber_per_serving>14</fiber_per_serving> <fat_per_serving>7</fat_per_serving>
<kj_per_serving>1400</kj_per_serving> </food_item> <food_item type="grain"> <name>Wheatgerm</name> <carbs_per_serving>1.5</carbs_per_serving> <fiber_per_serving>1</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>70</kj_per_serving> </food_item> </food_list>
The Requirement
Now, imagine we want to display the contents of the file in a table, and that we want to have a "counter" column that provides the count of each row. Something like this:
The Solution
We could achieve the above requirement using the XPath position() function, as follows:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="food_list"> <table border="1" style="background-color:#cccc00"> <tr> <th>Node Position</th> <th>Food Item</th> <th>Carbs (g)</th> <th>Fiber (g)</th> <th>Fat (g)</th> <th>Energy (kj)</th> </tr> <xsl:for-each select="food_item"> <tr> <td><b><xsl:value-of select="position()"/></b></td> <td><xsl:value-of select="name"/></td> <td><xsl:value-of select="carbs_per_serving"/></td> <td><xsl:value-of select="fiber_per_serving"/></td> <td><xsl:value-of select="fat_per_serving"/></td> <td><xsl:value-of select="kj_per_serving"/></td> </tr> </xsl:for-each> </table> </xsl:template> </xsl:stylesheet>
Operators
Here's a list of comparison operators you can use in your XPath expressions:
Operator = Is equal to. Description
Is not equal to. Is less than. Is greater than. Is less than or equal to. Is greater than or equal to.
<kj_per_serving>150</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Yam</name> <carbs_per_serving>30.5</carbs_per_serving> <fiber_per_serving>2</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>550</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Zucchini</name> <carbs_per_serving>1.5</carbs_per_serving> <fiber_per_serving>1.5</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>55</kj_per_serving> </food_item> <food_item type="seafood"> <name>Abalone</name> <carbs_per_serving>0</carbs_per_serving> <fiber_per_serving>0</fiber_per_serving> <fat_per_serving>1</fat_per_serving> <kj_per_serving>400</kj_per_serving> </food_item> <food_item type="seafood"> <name>Barramundi</name> <carbs_per_serving>0</carbs_per_serving> <fiber_per_serving>0</fiber_per_serving> <fat_per_serving>2</fat_per_serving> <kj_per_serving>390</kj_per_serving> </food_item> <food_item type="fruit"> <name>Apple</name> <carbs_per_serving>15</carbs_per_serving> <fiber_per_serving>2.5</fiber_per_serving> <fat_per_serving>0</fat_per_serving> <kj_per_serving>250</kj_per_serving> </food_item> <food_item type="fruit"> <name>Kiwi Fruit</name> <carbs_per_serving>7.5</carbs_per_serving> <fiber_per_serving>2.5</fiber_per_serving> <fat_per_serving>0</fat_per_serving> <kj_per_serving>150</kj_per_serving> </food_item> <food_item type="grain"> <name>Oatbran</name> <carbs_per_serving>62</carbs_per_serving> <fiber_per_serving>14</fiber_per_serving> <fat_per_serving>7</fat_per_serving> <kj_per_serving>1400</kj_per_serving> </food_item> <food_item type="grain"> <name>Wheatgerm</name> <carbs_per_serving>1.5</carbs_per_serving> <fiber_per_serving>1</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>70</kj_per_serving>
</food_item> </food_list>
The Requirement
This time, instead of displaying all 13 records (as we did in the previous lesson), we only want to display the first 5 records. Like this:
The Solution
We could modify the code from the previous lesson so that only the top 5 records are selected. We could achieve this using the XPath <= operator (along with the position() function), as follows:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="food_list"> <table border="1" style="background-color:#cccc00"> <tr> <th>Node Position</th> <th>Food Item</th> <th>Carbs (g)</th> <th>Fiber (g)</th> <th>Fat (g)</th>
<th>Energy (kj)</th> </tr> <xsl:for-each select="food_item[position() <= 5]"> <tr> <td><b><xsl:value-of select="position()"/></b></td> <td><xsl:value-of select="name"/></td> <td><xsl:value-of select="carbs_per_serving"/></td> <td><xsl:value-of select="fiber_per_serving"/></td> <td><xsl:value-of select="fat_per_serving"/></td> <td><xsl:value-of select="kj_per_serving"/></td> </tr> </xsl:for-each> </table> </xsl:template> </xsl:stylesheet>
<food_item type="vegetable"> <name>Potato</name> <carbs_per_serving>21.5</carbs_per_serving> <fiber_per_serving>2</fiber_per_serving> <fat_per_serving>1</fat_per_serving> <kj_per_serving>460</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Pumpkin</name> <carbs_per_serving>6</carbs_per_serving> <fiber_per_serving>1</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>150</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Yam</name> <carbs_per_serving>30.5</carbs_per_serving> <fiber_per_serving>2</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>550</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Zucchini</name> <carbs_per_serving>1.5</carbs_per_serving> <fiber_per_serving>1.5</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>55</kj_per_serving> </food_item> <food_item type="seafood"> <name>Abalone</name> <carbs_per_serving>0</carbs_per_serving> <fiber_per_serving>0</fiber_per_serving> <fat_per_serving>1</fat_per_serving> <kj_per_serving>400</kj_per_serving> </food_item> <food_item type="seafood"> <name>Barramundi</name> <carbs_per_serving>0</carbs_per_serving> <fiber_per_serving>0</fiber_per_serving> <fat_per_serving>2</fat_per_serving> <kj_per_serving>390</kj_per_serving> </food_item> <food_item type="fruit"> <name>Apple</name> <carbs_per_serving>15</carbs_per_serving> <fiber_per_serving>2.5</fiber_per_serving> <fat_per_serving>0</fat_per_serving> <kj_per_serving>250</kj_per_serving> </food_item> <food_item type="fruit"> <name>Kiwi Fruit</name> <carbs_per_serving>7.5</carbs_per_serving> <fiber_per_serving>2.5</fiber_per_serving> <fat_per_serving>0</fat_per_serving> <kj_per_serving>150</kj_per_serving> </food_item> <food_item type="grain">
<name>Oatbran</name> <carbs_per_serving>62</carbs_per_serving> <fiber_per_serving>14</fiber_per_serving> <fat_per_serving>7</fat_per_serving> <kj_per_serving>1400</kj_per_serving> </food_item> <food_item type="grain"> <name>Wheatgerm</name> <carbs_per_serving>1.5</carbs_per_serving> <fiber_per_serving>1</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>70</kj_per_serving> </food_item> </food_list>
The Requirement
This time, we will only display items that are either vegetables or fruit (remember, we have specified this using the "type" attribute). Like this:
The Solution
We could modify the code to test the value of the "type" attribute. We could achieve this using the XPath or operator to test that the value contains "vegetable" or "fruit", as follows:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="food_list"> <table border="1" style="background-color:#cccc00"> <tr> <th>Node Position</th> <th>Food Item</th> <th>Carbs (g)</th> <th>Fiber (g)</th> <th>Fat (g)</th> <th>Energy (kj)</th> </tr> <xsl:for-each select="food_item[(@type = 'vegetable') or (@type = 'fruit')]"> <tr> <td><b><xsl:value-of select="position()"/></b></td> <td><xsl:value-of select="name"/></td> <td><xsl:value-of select="carbs_per_serving"/></td> <td><xsl:value-of select="fiber_per_serving"/></td> <td><xsl:value-of select="fat_per_serving"/></td> <td><xsl:value-of select="kj_per_serving"/></td> </tr> </xsl:for-each> </table> </xsl:template> </xsl:stylesheet>
Number Operators
Here's a list of number operators you can use in your XPath expressions:
Operator + * Used for addition. Used for subtraction. Used for multiplication. Description
div mod
Used for division. Returns the modulus of two numbers. (The modulus is the remainder after you divide the two numbers).
Number Functions
Here's a list of functions you can use with numbers in your XPath expressions:
Function ceiling() floor() round() sum() Description Returns the smallest integer that is larger than the value provided. Returns the largest integer that is smaller than the value provided. Rounds the value provided to the nearest integer. Returns the sum of the two numbers provided.
Usage Example
The Source XML File
We'll use the following XML file, which contains a list of vegetables and their associated nutritional value:
<?xml version="1.0"?> <food_list> <food_item type="vegetable"> <name>Agar</name> <carbs_per_serving>81</carbs_per_serving> <fiber_per_serving>8</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>1280</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Asparagus</name> <carbs_per_serving>1</carbs_per_serving> <fiber_per_serving>1</fiber_per_serving> <fat_per_serving>0</fat_per_serving> <kj_per_serving>40</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Cabbage</name> <carbs_per_serving>0</carbs_per_serving> <fiber_per_serving>1</fiber_per_serving> <fat_per_serving>0</fat_per_serving>
<kj_per_serving>14</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Potato</name> <carbs_per_serving>21.5</carbs_per_serving> <fiber_per_serving>2</fiber_per_serving> <fat_per_serving>1</fat_per_serving> <kj_per_serving>460</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Pumpkin</name> <carbs_per_serving>6</carbs_per_serving> <fiber_per_serving>1</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>150</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Yam</name> <carbs_per_serving>30.5</carbs_per_serving> <fiber_per_serving>2</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>550</kj_per_serving> </food_item> <food_item type="vegetable"> <name>Zucchini</name> <carbs_per_serving>1.5</carbs_per_serving> <fiber_per_serving>1.5</fiber_per_serving> <fat_per_serving>0.5</fat_per_serving> <kj_per_serving>55</kj_per_serving> </food_item> </food_list>
The Requirement
This time, for each record, we'll display the carbohydrate value ("carbs"). We will also display a column that multiplies the number of carbs by 3 (representing 3 meals per day). Like this:
The Solution
We could modify the code from the previous lesson so that only the top 5 records are selected. We could achieve this using the XPath <= operator (along with the position() function), as follows:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="food_list"> <table border="1" style="background-color:#cccc00"> <tr> <th>Food Item</th> <th>Carbs Per Serving</th> <th>Carbs Per Day (3 serves per day)</th> </tr> <xsl:for-each select="food_item"> <tr> <td><xsl:value-of select="name"/></td> <td><xsl:value-of select="carbs_per_serving"/></td> <td><xsl:value-of select="carbs_per_serving * 3"/></td> </tr>
String Functions
Here's a list of string functions you might find useful for your XPath expressions:
Functions Description
starts-with(string1, string2) Returns true if the first string starts with the second string. contains(string1, string2) substring(stringoffsetlength) substring-before(string1, string2) substring-after(string1, string2) string-length(string) normalize-space(string) translate(string1, string2, string3) concat(string1, string2, ...) format-number(number1, string1, string2) Returns true if the first string contains the second string. Returns a section of the string. The section starts at offset (which is a number), and is as long as the value provided at length (also a number). Returns the part of string1 up until the first occurence of string2.
Returns the part of string1 after the first occurence of string2. Returns the length of string (i.e. the number of characters). Trims the leading and trailing space from string. Also replaces consecutive occurrences of white space with a single space. Returns string1 after any matching characters in string2 have been replaced by the characters in string3. Concatenates all strings (i.e. joins them together). Returns a formatted string version of number1 after applying string1 as a format string. string2 is an optional locale string.
Usage Example
The Requirement
Let's display the vegetable names in one column, and the string length of the vegetable name in another. Like this:
The Solution
We could use the string-length() function in our XSL file to return the length of the string:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="food_list"> <table border="1" style="background-color:#cccc00"> <tr> <th>Food Item</th> <th>String Length</th> </tr> <xsl:for-each select="food_item[position() <= 5]"> <tr> <td><xsl:value-of select="name"/></td> <td><xsl:value-of select="string-length(name)"/></td> </tr> </xsl:for-each> </table> </xsl:template> </xsl:stylesheet>
CSS
CSS (Cascading Style Sheets) allows web authors to apply styles to their web pages. More importantly, CSS enables them to do this independently of the HTML that makes up each web page. Therefore, as a web author, you can code your HTML without having to be concerned with what each HTML element is going to look like. You can change the look later using CSS. You'll find a wealth of information about CSS right here on Quackit. Read the CSS Tutorial, learn all the CSS properties that you can use, or just go straight to the code for some good old "cut & paste"!
Introduction
Cascading Style Sheets (CSS) have been seriously underated. Maybe it's because web designers think it's harder than what it is. The truth is, CSS is incredibly easy! With CSS, you can define all your common styles in an external Style Sheet. This way, if you want to change every occurence of a style throughout your site, you only need to update one place. This tutorial will show you how to implement CSS into your website. This tutorial will also show you how to create an external style sheet and link to it from your HTML page.
About CSS
What does CSS stand for?
CSS stands for Cascading Style Sheets.
What is CSS?
CSS is a language that you can use to define styles against any HTML element. These styles are set using CSS properties.For example, you can set font properties (size, colors, style etc), background images, border styles, and much more. Cascading Style Sheets, level 1 (CSS1) became a W3C Recommendation in December 1996. It describes the CSS language as well as a simple visual formatting model. CSS2, which became a W3C recommendation in May 1998, builds on CSS1 and adds support for media-specific style sheets (e.g. printers and aural devices), downloadable fonts, element positioning and tables. As of this writing, CSS3 is currently under development.
CSS Advantages
HTML has its limitations when it comes to layout. Sure, you have 6 different levels of headings and 6 different sizes of fonts. You also have tables, and you have control over alignment etc. These are good enough to get a reasonable looking document that shows the true structure of information. However, it's a far cry from some of the excellent layout & design that we see in magazines and printed brochures etc. CSS helps us achieve such layouts. With CSS, you have much better control over the layout of your web pages. You can specify exactly how big a font will be, exactly where an element will be on a page, what the page will look like when printed, and much more. CSS can also save you a lot of time, particularly when maintaining a large site. Also, the World Wide Web Consortium (W3C) recommends that web developers use CSS tags instead of HTML tags wherever possible. The W3C are gradually phasing out quite a few of these HTML tags.
Advantages of CSS
y
y y y
CSS saves time When most of us first learn HTML, we get taught to set the font face, size, colour, style etc every time it occurs on a page. This means we find ourselves typing (or copying & pasting) the same thing over and over again. With CSS, you only have to specify these details once for any element. CSS will automatically apply the specified styles whenever that element occurs. Pages load faster Less code means faster download times. Easy maintenance To change the style of an element, you only have to make an edit in one place. Superior styles to HTML CSS has a much wider array of attributes than HTML.
Disadvantages of CSS
y
Browser compatibility Browsers have varying levels of compliance with Style Sheets. This means that some Style Sheet features are supported and some aren't. To confuse things more, some browser manufacturers decide to come up with their own proprietary tags.
Fortunately, browser compatibility is becoming less of an issue as the latest browser versions are much more standards-compliant than their earlier counterparts.
CSS Syntax
The CSS syntax consists of a set of rules. These rules have 3 parts: a selector, a property, and a value. You don't need to remember this in order to code CSS. Once you start coding CSS, you'll do so without thinking "this is a selector" or "that is a property". This should begin to make sense once you study the examples on this page. Syntax:
selector { property: value }
The selector is often the HTML element that you want to style. For example:
h1 { color: blue }
This code tells the browser to render all occurences of the HTML h1 element in blue.
Grouping Selectors
You can apply a style to many selectors if you like. Just separate the selectors with a comma.
h1,h2,h3,h4,h5,h6 { color: blue }
Readability
You can make your CSS code more readable by spreading your style declarations across multiple lines. You can also indent your code if you like. This doesn't affect how your code is rendered it just makes it easier for you to read.
h1 { color:blue; font-family:arial,helvetica,"sans serif"; font-size:150%; }
OK, so you've now learned about the CSS syntax. But how do you incorporate this syntax into your website? The next lesson will show you how to incorporate CSS into your HTML documents.
Implementing CSS
There are 4 ways of implementing CSS: declare inline, embed into the head of your document, link to an external CSS file, import a CSS file.
Inline CSS
Style sheet information is applied to the current element. Instead of defining the style once, then applying the style against all instances of an element (say the <P> tag), you only apply the style to the instance you want the style to apply to. For example:
<P style="color:#ff9900"> CSS tutorial. </p>
Embedded CSS
You embed CSS information into an HTML document using the 'style' element. You do this by embedding the CSS information within <style>...</style> tags in the head of your document. For example, place the following code between the <head>...</head> tags of your HTML document:
<style type="text/css" media=screen> p {color:#ff9900;} </style>
Now, whenever any of those elements are used within the body of the document, they will be formatted as instructed in the above style sheet.
External CSS
An external style sheet is a separate file where you can declare all the styles that you want to use throughout your website. You then link to the external style sheet from all your HTML pages.
This means you only need to set the styles for each element once. If you want to update the style of your website, you only need to do it in one place. For example: 1. Type the following into a plain text file, and save with a .css extension (i.e. external_style_sheet.css).
2. 3. p {font-family: georgia, serif; font-size: x-small;} 4. h1 {color: #000099; } 5.
6. Add the following between the <head>...</head> tags of all HTML documents that you want to reference the external style sheet.
7. 8. <link rel="stylesheet" href="external_style_sheet.css" type="text/css"> 9.
Imported CSS
You can use the @import rule to import rules from other style sheets. Add either of the following between the <head>...</head> tags of all HTML documents that you want to import a style sheet into.
@import "imported_style_sheet.css"; @import url("imported_style_sheet.css");
CSS Class
A few lessons ago, we learned about selectors. You may recall that selectors are the things we apply a style against. In our examples, our selectors were all HTML elements. For example, we decided to make the h1 element blue. Now, that works well if you want all headings to be blue. But what if you only want some of your headings to be blue? Perhaps you want the color of your headings to reflect the section of the site that you're in. Sounds like you need to use classes! In CSS, classes allow you to apply a style to a given class of an element. To do this, you link the element to the style by declaring a style for the class, then assigning that class to the element.
You declare a CSS class by using a dot (.) followed by the class name. You make up the class name yourself. After the class name you simply enter the properties/values that you want to assign to your class.
.class-name { property:value; }
If you want to use the same class name for multiple elements, but each with a different style, you can prefix the dot with the HTML element name.
html-element-name.class-name { property:value; }
CSS Class
CSS classes can be very useful
CSS id
IDs allow you to assign a unique identifier to an HTML element. This allows you to define a style that can only be used by the element you assign the ID to.
CSS ID Syntax
The syntax for declaring a CSS ID is the same as for classes - except that instead of using a dot, you use a hash (#).
#id-name { property:value; }
Again, similar to classes, if you want to use the same id name for multiple elements, but each with a different style, you can prefix the hash with the HTML element name.
html-element-name#id-name { property:value; }
CSS ID Example
<head> <style type="text/css"> h1#css-section { color:#000099 } p#css-section { color:#999999; } </style> </head> <body> <h1 id="css-section">CSS ID</h1> <p id="css-section">CSS IDs can be very useful</p> </body>
CSS ID
CSS IDs can be very useful
IDs vs Classes
Given classes and IDs are very similar, you may be wondering which one to use. This depends on the situation.
Another useful thing about IDs is that you can use the Document Object Model (DOM) to refer to them. This enables you to use JavaScript/DHTML techniques to build a much more interactive web site.
CSS Font
CSS font properties enable you to change the look of your text. For example, you can assign a font family, apply bold or italic formatting, change the size and more.
This results in: This text is rendered in either georgia, garamond, or the default serif font (depending on which font the user's system has).
This results in: If your computer has an expanded version of the font being used, this text will be stretched.
<p style="font:italic small-caps bold 20px georgia,garamond,serif;">The styles for this text has been specified with the 'font' shorthand property.</p>
THE STYLES FOR THIS TEXT HAS BEEN SPECIFIED WITH THE 'FONT' SHORTHAND PROPERTY.
CSS Text
Apart from the various CSS font properties, there are other properties that can assist in styling your text. For example, you can change the color of text, align text, add decoration properties and more. In CSS, text can be styled using the properties listed below. Using this list, you can learn how to use each css text property and what it looks like in a browser.
This results in: This text is indented by 50 pixels. What this means is that the first line of the paragraph will be indented by 50 pixels, but the following lines will not be indented. The text will need to wrap before you can see the indent - hence all this text!
This results in: T his t ext has let t er sp acing app lied
This results in: This text has a line over the top This text has a line through the middle This text has a line underneath
This hyperlink has no underline
<p style="text-transform:uppercase;">This text has been transformed to uppercase</p> <p style="text-transform:lowercase;">THIS TEXT HAS BEEN TRANSFORMED TO LOWERCASE</p> <p style="text-transform:capitalize;">this text has been capitalized.</p>
This results in: THIS TEXT HAS BEEN TRANSFORMED TO UPPERCASE THIS TEXT HAS BEEN TRANSFORMED TO LOWERCASE this text has been capitalized.
This results in: text runs from This can be useful for languages where the .This text is running from right to left ...Not so useful for english though .right to left
CSS unicode-bidi
Use this in conjunction with the direction property to determine the direction of the text. Possible values: normal, embed, bidi-override, and inherit.
<p style="direction:rtl;unicode-bidi:bidi-override;">This text is running from right to left. This can be useful for languages where the text runs from right to left. Not so useful for english though...</p>
This results in: useful for languages where the text runs from This can be .This text is running from right to left ...Not so useful for english though .right to left
If your browser supports the CSS text-shadow property, this text will have a shadow.
This results in: This text has a line break and the white-space pre setting tells the browser to honor it just like the HTML pre tag.
Determines whether the background image repeats (tiles) or not. For info on the possible values, see the background-repeat page.
<p style="height:100px;background-image:url(/pix/smile.gif);backgroundrepeat:no-repeat;">This background image does not repeat. </p>
This results in: This background image is positioned 100 pixels in from the left.
This results in: This background image is fixed - it doesn't scroll with its outer container. This example uses the CSS overflow property to force the box to scroll when there's too much text to fit in the box.
Shorthand Code
You can use the background property to set all the background properties at once. For example:
<p style="height:100px;width:150px;overflow:scroll;background:url(/pix/smile.gif ) repeat fixed;">This paragraph tag has been styled using the 'background' property, which is shorthand for setting multiple properties for an HTML element. </p>
This results in: This paragraph tag has been styled using the 'background' property, which is shorthand for setting multiple properties for an HTML element.
CSS Border
The following CSS border codes demonstrate the various CSS properties you can use to apply styles to the border of any HTML element. CSS allows you to set styles for the border of any HTML element. It also provides you with a way of setting border styles for one or more sides of an element.
This results in: This text has border styles applied using the border-width, border-style, and border-color properties.
This results in: This text has border styles applied using the border property.
Border Styles
Borders can have the following styles.
<p style="border:4px 'solid'.</p> <p style="border:4px 'dotted'.</p> <p style="border:4px 'dashed'.</p> <p style="border:4px 'double'.</p> <p style="border:4px 'groove'.</p> <p style="border:4px 'ridge'.</p> <p style="border:4px 'inset'.</p> <p style="border:4px 'outset'.</p> <p style="border:4px 'hidden'.</p>
solid blue;">This text has a border style of dotted blue;">This text has a border style of dashed blue;">This text has a border style of double blue;">This text has a border style of groove blue;">This text has a border style of ridge blue;">This text has a border style of inset blue;">This text has a border style of outset blue;">This text has a border style of hidden blue;">This text has a border style of
This results in: This text has a border style of 'solid'. This text has a border style of 'dotted'. This text has a border style of 'dashed'. This text has a border style of 'double'. This text has a border style of 'groove'. This text has a border style of 'ridge'. This text has a border style of 'inset'. This text has a border style of 'outset'. This text has a border style of 'hidden'.
Explicit Properties
y y y y y y y y y y y y
border-bottom-color border-bottom-style border-bottom-width border-left-color border-left-style border-left-width border-right-color border-right-style border-right-width border-top-color border-top-style border-top-width
Example:
<p style="border-bottom-width:4px;border-bottom-style:double;border-bottomcolor:blue;">This text has a bottom border.</p>
Shorthand Properties
The following properties provide you with a more concise way of specifying border properties for each side.
y y y y
Example:
<p style="border-bottom:4px double blue;">This text has a bottom border.</p>
CSS Margin
Related: CSS margin Property
The following CSS margin codes demonstrate the various CSS properties you can use to apply styles to the border of any HTML element. Margins define the space around the element. CSS margins are specified in a similar way to borders - they can be set individually for each side, or all sides at once.
This results in: This text has a margin of 20 pixels on all four sides. It is nested within a div with a border to make it easier to see the effect of the margin.
Example:
<p style="border:1px solid orange;margin-left:60px;">This text has a left margin of 60 pixels.</p>
Shorthand Property
This method uses a shorthand property for setting margin-top, margin-right, margin-bottom, and margin-left in the one place. This method is quicker. It also uses less code than the
previous method. Actually, it's the same property that we used in our first example (i.e. the margin property). The only difference is that we apply multiple values against it. Code:
<div style="border:1px solid blue;width:200px;"> <p style="border:1px solid orange;margin:40px 10px 1px 40px;"> This text has a different sized margin for each side. It is nested within a div with a border to make it easier to see the effect of the margin. </p> </div>
Result:
This text has a different sized margin for each side. It is nested within a div with a border to make it easier to see the effect of the margin.
Variations
You don't need to provide different values for all four sides. You can provide one, two, three, or four values. Here's how it works: If there is only one value, it applies to all sides. If there are two values, the top and bottom margins are set to the first value and the right and left margins are set to the second. If there are three values, the top is set to the first value, the left and right are set to the second, and the bottom is set to the third. If there are four values, they apply to the top, right, bottom, and left, respectively. In other words:
margin:10px; y
margin:10px 20px; y y
Top and bottom have a margin of 10 pixels. Right and left have a margin of 20 pixels.
CSS Padding
Related: CSS 'Cellpadding' CSS padding Property
Padding defines the space between the element's border and its content. CSS padding is specified just like margins - they can be set individually for each side, or all sides at once.
Example:
<p style="border:1px solid orange;padding-left:60px;">This text has left padding of 60 pixels.</p>
Shorthand Property
Along similar lines to the margin shorthand property, the padding property is shorthand for padding-top, padding-right, padding-bottom, and padding-left. Code:
<p>With padding:</p> <div style="border:1px solid orange;width:100px;padding:20px 10px 0px 100px;"> Padded div </div> <p>Without padding:</p> <div style="border:1px solid orange;width:100px;"> Non-padded div </div>
Without padding:
Non-padded div
As you can see, applying padding to an element can affect the size of that element. In the example above, both <div> elements are specified to be 100 pixels wide. However, the padding on the first <div> pushes the size out, resulting in a larger <div>.
Variations
Again, as with margin, you don't need to provide different values for all four sides. You can provide one, two, three, or four values. Here's how it works: If there is only one value, it applies to all sides. If there are two values, the top and bottom paddings are set to the first value and the right and left paddings are set to the second. If there are three values, the top is set to the first value, the left and right are set to the second, and the bottom is set to the third. If there are four values, they apply to the top, right, bottom, and left, respectively. In other words:
padding:10px; y
padding:10px 20px; y y
Top and bottom have padding of 10 pixels. Right and left have padding of 20 pixels.
CSS Lists
CSS includes a number of list properties to help you style your HTML lists.
List item one List item two List item one List item two
List Style
The list-style property is shorthand for setting the list properties.
<ul style="list-style:square inside;"> <li>List item one</li> <li>List item two</li> </ul>
Marker Offset
Used in conjunction with display:marker, marker-offset specifies the nearest border edges of the marker box and its associated principal box.
<ul> <li style="display:marker;marker-offset:10px;">List item one</li> <li>List item two</li>
</ul>
CSS Positioning
The term "CSS positioning" refers to using CSS to position elements on your HTML page. CSS allows you to position any element precisely where you want it. You can specify whether you want the element positioned relative to its natural position in the page or absolute based on its parent element. Absolute positioning can be very useful for creating advanced layouts and cool visual effects such as overlapping elements to present a layered effect.
Relative Positioning
To perform relative positioning in CSS you use position:relative; followed by the desired offset from either top, right, bottom or left
<div style="position:relative;left:80px;backgroundcolor:yellow;width:100px;"> This div has relative positioning. </div>
This example offsets the element 80 pixels from the left of where it would have been. If we had specified top, it would appear 80 pixels below where it would have been. It's important to note that other elements are not affected by this element's offset. Therefore, overlapping may occur.
Absolute Positioning
To perform absolute positioning in CSS you use position:absolute; followed by the desired offset.
<div style="position:absolute;top:100px;left:60px;background-color:yellow;"> This div is absolutely positioned 100 pixels from the top and 60 pixels from the left of its containing block. </div>
Fixed Positioning
Fixed positioning allows you to fix the position of an element to a particular spot on the page regardless of scrolling.
<div style="position:fixed;top:100px;left:60px;width:180px;backgroundcolor:red;"> This div is using a fixed position of 100 pixels from the top and 60 pixels from the left of its containing block. When this page scrolls, this box will remain in a fixed position - it won't scroll with the rest of the page. Go on - SCROLL! </div>
CSS Float
The CSS float property enables you to determine where to position an element relative to the other elements on the page. When you use the float property, other elements will simply wrap around the element you applied the float to. Example code:
<div style="width:300px;"> <h1 style="float:left;margin-right:10px;">CSS float</h1> <p>If your browser supports the CSS float Property, this text will be flowing around the heading. If this does not seem to work, it could be a browser compatibility thing...</p> </div>
CSS float
If your browser supports the CSS float Property, this text will be flowing around the heading. If this does not seem to work, it could be a browser compatibility thing...
CSS Layers
In CSS, layers refer to applying the z-index property to elements that overlap with each other. The z-index property, when used in conjunction with the position property, enables you to specify which element should appear on top in the event of an overlap. An overlap can easily
occur when using the position property, and this is often desirable when creating advanced layouts. Example code:
<div style="background-color:red; width:100px; height:100px; position:relative; top:10px; left:80px; z-index:2;"> </div> <div style="background-color:yellow; width:100px; height:100px; position:relative; top:-60px; left:35px; z-index:1;"> </div>
The css text-align property applies to the contents of the block-level element - it doesn't need to be text. For more information on usage, see the text-align property page.
Note that at the time of writing, browser support for vertical-align was limited. For more information on usage, see the vertical-align property page.