Introduction
XSLT stands for Extensible Stylesheet Language for Transformations. As you can see, there is no XML in name, and that is just strange if you
think about it, because XSLT is used for XML document transformation (transform input XML document into output (no necessary XML) document).
One of the advantage of parsing and handling XML documents with XSLT is that XSLT is W3C recommendation (so you have standard tool set and
concepts that are transferable).
Please download example from my google code repository:
XSLT: download
XML example file: download
Concepts
XSLT language should be based on pattern matching. Most of your stylesheet consist of rules (called templates) used to transform
XML documents. Each rule says, "When you see part of a document that look like this (when you see specific tag in XML document), here's how you convert
it into something else.". XSLT is heavily influenced by the design of functional programming languages (Lisp, Scheme, F#, Haskel, ...).
You can think of templates as equivalent to functions in functional languages. In XSLT you do everything with recursion, as in any other F. language.
In oder to follow this tutorial, you need to understand what XML is all about. It is (XML) basically document that holds data and describe meaning of data. You can
describe data by defining schema's (similar to database schema's...).
When we create XML stylesheets we use two standards: XSLT and XPath. You can see my short XPath tutorial if you are not familiar with
this standard. There is also XQuery that is more similar to SQL, but we will not use it here.
There are number of free XSLT processors (Xalan, Saxon, Microsoft XSLT Processor, Altova XSLT Engine). We will use Altova XSLT Engine that is used
in their program XML Spy.
Example
This tutorial will show how to transform XML to HTML file. We will use XML files from
US National Weather Service
They already include XSLT in their XML files, so you need to remove that file name and assign XSL file we will create here.
We will transform weather XML file in rather simple HTML file.
Here's how XML file look like:
You can see that this XML file is quite simple. Only one root element and bunch of child elements.
From this XML file we will create HTML page that looks like this:
You can see that page is also pretty simple. Only subset of elements are shown.
XSLT file for this page looks like this:
As you can see we are using XSLT 1.0 for browser compatibility reasons.
Line-by-line review:
4-6: We match root of the element and then apply templates for all other child elements.
8-17: Create HTML HEAD element and fill some styles.
18: Start BODY element filling.
20 and 24: Set some DIV's (not important)
21: Construct img element by combining two elements from XML.
25: We will not show all elements, we are interested only in "location", "observation_time", "pressure_string" and "wind_string".
30-34: For temperature element we will use special template.
35-37: For all other elements we will use same template. In this template we
use another template for extracting sensible name from XML element tag names (why not use it if they are mostly ok).
38-52: If element tag name contains "string" string then we will remove it. If element tag name contains only '_' char, then replace that char with space ' '. If this is not the case, then just return tag name. In this way we can use single template for processing all elements.
Ok that's it! Let's move on another tutorial...
Showing posts with label XML. Show all posts
Showing posts with label XML. Show all posts
Friday, December 24, 2010
Thursday, December 16, 2010
Recursion in XSLT
Introduction
I like recursion! It is pure and formal. When you solve problems using recursion you code look cleaner & leaner & meaner! But problem with recursion is that
it is hard to imagine it. You can easily imagine how for loop works, but when you solve complex artificial intelligence algorithms using trees it can get
quite complex and error prone (min-max algorithms for example). I myself like to use recursion only when it might provide substantially more elegant
solution that other methods, and make recursion flow as easy to follow as possible (refactor it to special method,...).
That's all great, but in XSLT (like in any functional language) we are forced to use recursion in situations when we need create functions (templates)
that are not included in XSLT 2.0/1.0 spec. Also using recursion in XSLT is natural way of traversing XML (or any other tree like structured document).
To work with recursion in XSLT, you need to be familiar with couple of things in XSLT. First are off course templates. Templates are analog (or
at least similar) to functions in functional language (Scheme, LISP, F#,...). They have can have parameters and variables. Variables in XSLT are immutable
(they state cannot be changed after first value assignment). For example String object in Java is also immutable. Templates can call itself for recursive calls.
There are no loops in XSLT (don't try to find them). There is xls:forEach but it behave different than loops in imperative language.
Second thing is XPath. XPath is a syntax used to describe parts of XML document. XPath is designed to be used inside an attribute in XML
document. The syntax is a mix of basic programming language expressions and Unix-like path expression.
Example
To show how process XML document using XSLT and recursion we will use example XML document. This document describes F1 2010 season overview for four races.
It shows name of grand Prix (race), data of race, winning driver name, winning team name, no of laps, winning time.
We will transform this XML document into another document. The customer want to have data within same XML element (tag) put into single XML element
separated by comma. It is maybe strange request, but it is constructed like that to show how recursion is used in XSLT.
Example of transformated XML:
Solution:
You can download full file from my google code repository. Here I will attach image:
Recursion start at line 34. Here we create template with two parameters. First parameter is sequence (in XPath 2.0) or node-set (in XPath 1.0) of values we are going to traverse and concatenate with delimiter. Second parameter is resulting string that is printed at the end of template (line: 48) (at the end of recursion).
38 check if recursion should stop. It stops if there are no values left (or there was no values at first place) in sequence.
If sequence is not empty, then we go into recursion and call template (line: 40) again with following parameters:
41: Rest of values in sequence (everything after the first item -- position() > 1).
42: Concatenate first value from sequence into resulting string (we only handle first value differently).
Finite!
I like recursion! It is pure and formal. When you solve problems using recursion you code look cleaner & leaner & meaner! But problem with recursion is that
it is hard to imagine it. You can easily imagine how for loop works, but when you solve complex artificial intelligence algorithms using trees it can get
quite complex and error prone (min-max algorithms for example). I myself like to use recursion only when it might provide substantially more elegant
solution that other methods, and make recursion flow as easy to follow as possible (refactor it to special method,...).
That's all great, but in XSLT (like in any functional language) we are forced to use recursion in situations when we need create functions (templates)
that are not included in XSLT 2.0/1.0 spec. Also using recursion in XSLT is natural way of traversing XML (or any other tree like structured document).
To work with recursion in XSLT, you need to be familiar with couple of things in XSLT. First are off course templates. Templates are analog (or
at least similar) to functions in functional language (Scheme, LISP, F#,...). They have can have parameters and variables. Variables in XSLT are immutable
(they state cannot be changed after first value assignment). For example String object in Java is also immutable. Templates can call itself for recursive calls.
There are no loops in XSLT (don't try to find them). There is xls:forEach but it behave different than loops in imperative language.
Second thing is XPath. XPath is a syntax used to describe parts of XML document. XPath is designed to be used inside an attribute in XML
document. The syntax is a mix of basic programming language expressions and Unix-like path expression.
Example
To show how process XML document using XSLT and recursion we will use example XML document. This document describes F1 2010 season overview for four races.
It shows name of grand Prix (race), data of race, winning driver name, winning team name, no of laps, winning time.
Bahrain 14/03/2010 Fernando Alonso Ferrari 49 Australia 28/03/2010 Jenson Button McLaren-Mercedes 58 Malaysia 04/04/2010 Sebastian Vettel RBR-Renault 56 China 18/04/2010 Jenson Button McLaren-Mercedes 56
We will transform this XML document into another document. The customer want to have data within same XML element (tag) put into single XML element
separated by comma. It is maybe strange request, but it is constructed like that to show how recursion is used in XSLT.
Example of transformated XML:
Bahrain, Australia, Malaysia, China 14/03/2010, 28/03/2010, 04/04/2010, 18/04/2010 ...1:39:20.396, 1:33:36.531, 1:33:48.412, 1:46:42.163
Solution:
You can download full file from my google code repository. Here I will attach image:
Recursion start at line 34. Here we create template with two parameters. First parameter is sequence (in XPath 2.0) or node-set (in XPath 1.0) of values we are going to traverse and concatenate with delimiter. Second parameter is resulting string that is printed at the end of template (line: 48) (at the end of recursion).
38 check if recursion should stop. It stops if there are no values left (or there was no values at first place) in sequence.
If sequence is not empty, then we go into recursion and call template (line: 40) again with following parameters:
41: Rest of values in sequence (everything after the first item -- position() > 1).
42: Concatenate first value from sequence into resulting string (we only handle first value differently).
Finite!
Saturday, October 9, 2010
XPath tutorial for busy programmer
Introduction
As w3.org standard say: XPath is a language for addressing parts of an XML document. Ok...that is simple enough. XPath is just basically a mean to traverse XML document and perform search on it. We can use structure of the XML document (semantics of data), or on data itself to perform that search. We can use XPath in XML transformations (XSLT), in SOA (BPEL language). And as I can see jQuery use similar logic for its selector search operations.
XML document
XPath can query any part of the XML document (any node at any level - XML documents are treated as trees of nodes). As a result of search, XPath may return null, string, number or another XML node (that can also be queried). XPath is used to navigate through elements or attribute of an XML document.
We will use following XML document:
Basic node selection
To navigate through XML document we are using path expressions. The most to common expressions we will use are slashes : single ("/"), or double ("//").
Single slash will perform search from root node. In our XPath search as: "/game-systems/system/type" will return following result (in XMLSpy):
Double slash will perform traverse through XML tree and find out all nodes that match the selection no matter where they are in XML. So selection: "//type" in our example will produce same result as previous example.
Also common expression path to select XML nodes are: "@, ., ..".
"@" is used to select attribute, as in: "/game-systems/system/emulator/@usable", where we select value of usable attribute in system node.
"." will select current node, and ".." parent node. This is similar like selecting file path in file system!
Selecting parent of emulator node (hint: system): "/game-systems/system/emulator/..".
Finding specific node
To find some specific nodes we use predicates. With this construction we can perform search to find node with specific element or attribute value. Also we can extract specific result from node set result (if there is more that one node as result from previously search). Predicates are always embedded in square brackets.
Finding first system/emulator value can be done with following search:
"/game-systems/system[1]/emulator".
To find all system name with usable emulator we will write:
"/game-systems/system/emulator[@usable='true']/../name" -- here we use ".." as a way to move up to previous element in XML tree.
Finding node-set relative to the current node
We can also use XML tree structure (you know, children, parents and stuff) to find specific nodes.
For example, we can write previous example as follows: "/game-systems/system/emulator[@usable='true']/ancestor::system/name.
This is somewhat longer but it does same thing. Here we are using ancestor function that return ancestor of current element (system in this case). You can also search for child, attributes, descendants and similar searches that you can also perform (in most cases) using basic node selectors and predicates.
As w3.org standard say: XPath is a language for addressing parts of an XML document. Ok...that is simple enough. XPath is just basically a mean to traverse XML document and perform search on it. We can use structure of the XML document (semantics of data), or on data itself to perform that search. We can use XPath in XML transformations (XSLT), in SOA (BPEL language). And as I can see jQuery use similar logic for its selector search operations.
XML document
XPath can query any part of the XML document (any node at any level - XML documents are treated as trees of nodes). As a result of search, XPath may return null, string, number or another XML node (that can also be queried). XPath is used to navigate through elements or attribute of an XML document.
We will use following XML document:
Arcade MAME true Sony PSP false Console Nintendo Wii true Console Sony PS2 true
Basic node selection
To navigate through XML document we are using path expressions. The most to common expressions we will use are slashes : single ("/"), or double ("//").
Single slash will perform search from root node. In our XPath search as: "/game-systems/system/type" will return following result (in XMLSpy):
Double slash will perform traverse through XML tree and find out all nodes that match the selection no matter where they are in XML. So selection: "//type" in our example will produce same result as previous example.
Also common expression path to select XML nodes are: "@, ., ..".
"@" is used to select attribute, as in: "/game-systems/system/emulator/@usable", where we select value of usable attribute in system node.
"." will select current node, and ".." parent node. This is similar like selecting file path in file system!
Selecting parent of emulator node (hint: system): "/game-systems/system/emulator/..".
Finding specific node
To find some specific nodes we use predicates. With this construction we can perform search to find node with specific element or attribute value. Also we can extract specific result from node set result (if there is more that one node as result from previously search). Predicates are always embedded in square brackets.
Finding first system/emulator value can be done with following search:
"/game-systems/system[1]/emulator".
To find all system name with usable emulator we will write:
"/game-systems/system/emulator[@usable='true']/../name" -- here we use ".." as a way to move up to previous element in XML tree.
Finding node-set relative to the current node
We can also use XML tree structure (you know, children, parents and stuff) to find specific nodes.
For example, we can write previous example as follows: "/game-systems/system/emulator[@usable='true']/ancestor::system/name.
This is somewhat longer but it does same thing. Here we are using ancestor function that return ancestor of current element (system in this case). You can also search for child, attributes, descendants and similar searches that you can also perform (in most cases) using basic node selectors and predicates.
Subscribe to:
Posts (Atom)