1 copyright (c) [2001]. roger l. costello. all rights reserved. using xslt and xpath to enhance html...
Post on 21-Dec-2015
221 views
TRANSCRIPT
1Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Using XSLT and XPath to Enhance HTML Documents
Roger L. Costello
XML Technologies
2Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Acknowledgement
• I wish to thank David Jacobs for showing me a new way of looking at HTML and XSLT/XPath
• Many of the examples that I use in this tutorial come straight from David's excellent paper, Rescuing XSLT from Niche Status (see http://www.xfront.com)
3Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Note
• For brevity, instead of using the term XSLT/XPath, I will simply call it XSL.
4Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Multiple Output Formats
• XSL may be used to generate either HTML, XML, or text
XSL Processor
XSL
XML HTML (or XML or text)
5Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
xalan/xt/saxon• xalan: A free XSL processor, implemented in Java, from Apache (http://www.apache.org/) • xt: A free XSL processor, implemented in Java, from James Clark (http://www.jclark.com/)• saxon: A free XSL processor, implemented in Java, from Michael Kay (http://users.iclway.co.uk/mhkay/saxon
xalan/xt/saxon
XML XSL
HTML (or XML or text)
Invoking from a DOS command line: run-xalan FitnessCenter.xml FitnessCenter.xsl FitnessCenter.html run-xt FitnessCenter.xml FitnessCenter.xsl FitnessCenter.html run-saxon FitnessCenter.xml FitnessCenter.xsl FitnessCenter.html
6Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Styling XML Documents using Internet Explorer
• Here are the steps to using Internet Explorer for styling your XML documents:– First, download the latest version of Internet
Explorer (at this time the latest version is 5.5)– Download Microsoft's XSL plugin,
MSXML3.0 from http://www.xmlspy.com/download_components.html and then install it (double click on the .exe file)
– Follow the instructions on the next slide:
7Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
The following instructions come from this web page:
http://www.netcrucible.com/xslt/msxml-faq.htm#Q3
Download xmlinst.exe from http://msdn.microsoft.com/msdn-files/027/001/469/xmlinst.exe
Double click on the downloaded file. This will result in extracting some files.
Open a DOS window. Change directory to where you placed the extracted files. Set the pathenvironment variable to include the directory where regsvr32.exe is located (on Windows 98 it ison c:\windows\system) Then type the following commands:
xmlinst regsvr32 msxml3.dll
Styling XML Documents using Internet Explorer (cont.)
8Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Styling XML Documents using Internet Explorer (concluded)
• Lastly, when you create your XML document you must put a stylesheet PI at the top to tell IE what stylesheet to use:
<?xml version="1.0"?><?xml-stylesheet type="text/xsl" href="FitnessCenter.xsl"?><FitnessCenter> <Member level="platinum"> <Name>Jeff</Name> <Phone type="home">555-1234</Phone> <Phone type="work">555-4321</Phone> <FavoriteColor>lightgrey</FavoriteColor> </Member></FitnessCenter>
Add thisstylesheetPI to thetop of your XMLdocument
9Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
HTML Generation
• We will first use XSL to generate HTML documents• When generating HTML, XSL should be viewed as a
tool to enhance HTML documents.– That is, the HTML documents may be enhanced
by extracting data out of XML documents– XSL provides elements (tags) for extracting the
XML data, thus allowing us to enhance HTML documents with data from an XML document
10Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Enhancing HTML Documents with XML Data
XML Document
HTML Document(with embeddedXSL elements)
XSL element
XML data
XSLProcessor
XML data
11Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Enhancing HTML Documents with the Following XML Data
<?xml version="1.0"?><?xml-stylesheet type="text/xsl" href="FitnessCenter.xsl"?>
<FitnessCenter> <Member level="platinum"> <Name>Jeff</Name> <Phone type="home">555-1234</Phone> <Phone type="work">555-4321</Phone> <FavoriteColor>lightgrey</FavoriteColor> </Member></FitnessCenter>
FitnessCenter.xml
12Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
HTML Document in an XSL Template
<?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="html"/>
<xsl:template match="/"> <HTML> <HEAD> <TITLE>Welcome</TITLE> </HEAD> <BODY> Welcome! </BODY> </HTML> </xsl:template>
</xsl:stylesheet>
FitnessCenter.xsl (see html-example01)
Note how wehave the HTMLdocument embedded withinan XSL template
13Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Note
• The HTML is embedded within an XSL template, which is an XML document– Consequently, the HTML must be well formed, i.e.,
every start tag must have an end tag• Because the HTML is embedded within an XSL template,
we are able to add XSL elements to the HTML, allowing us to extract data out of XML documents
• Let's customize the HTML welcome page by putting in the member's name. This is achieved by extracting the name from the XML document. We use an XSL element to do this.
14Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Extracting the Member Name<?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="html"/>
<xsl:template match="/"> <HTML> <HEAD> <TITLE>Welcome</TITLE> </HEAD> <BODY> Welcome <xsl:value-of select="/FitnessCenter/Member/Name"/>! </BODY> </HTML> </xsl:template>
</xsl:stylesheet>
(see html-example02)
15Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Note
• Notice how we have enhanced the HTML document by using data from the XML document!
16Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Extracting a Value from an XML Document,
Navigating the XML Document• Extracting values:
– use the <xsl:value-of select="…"/> XSL element
• Navigating:
– The slash ("/") indicates parent/child relationship
– A slash at the beginning of the path indicates that it is an absolute path, starting from the top of the XML document
/FitnessCenter/Member/Name
"Start from the top of the XML document, go to the FitnessCenter element, from there go to the Member element, and from there go to the Name element."
17Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Document/
PI<?xml version=“1.0”?>
ElementFitnessCenter
ElementMember
ElementName
ElementPhone
ElementPhone
ElementFavoriteColor
TextJeff
Text555-1234
Text555-4321
Textlightgrey
18Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Extract the FavoriteColor and use it as the bgcolor
<?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="html"/>
<xsl:template match="/"> <HTML> <HEAD> <TITLE>Welcome</TITLE> </HEAD> <BODY bgcolor="{/FitnessCenter/Member/FavoriteColor}"> Welcome <xsl:value-of select="/FitnessCenter/Member/Name"/>! </BODY> </HTML> </xsl:template>
</xsl:stylesheet>
(see html-example03)
19Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Note
Attribute values cannot contain "<" nor ">" - Consequently, the following is NOT valid: <Body bgcolor="<xsl:value-of select='/FitnessCenter/Member/FavoriteColor'/>">
To extract the value of an XML element and use it as an attributevalue you must use curly braces: <Body bgcolor="{/FitnessCenter/Member/FavoriteColor}">
Evaluate the expression within the curly braces. Assign the valueto the attribute.
20Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Extract the Home Phone Number<?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="html"/>
<xsl:template match="/"> <HTML> <HEAD> <TITLE>Welcome</TITLE> </HEAD> <BODY bgcolor="{/FitnessCenter/Member/FavoriteColor}"> Welcome <xsl:value-of select="/FitnessCenter/Member/Name"/>! <BR/> Your home phone number is: <xsl:value-of select="/FitnessCenter/Member/Phone[@type='home']"/> </BODY> </HTML> </xsl:template>
</xsl:stylesheet>
(see html-example04)
21Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Note
In this example we want "the Phone element where the valueof its type attribute equals 'home' ":
<xsl:value-of select="/FitnessCenter/Member/Phone[@type='home']"/>
The expression within […] is called a "predicate". Its purposeis to filter.
Note the use of the single quotes within the double quotes. select=" … ' …' …"
22Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Review - HTML Table
<table border=“1” width=“100%”>
</table>
<tr>
<tr>
<tr> </tr>
</tr>
</tr><th> </th>
<th> </th>
<th> </th>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
This will create a table with 3 rows - the first row contains a headerfor each column. The next two rows contains the table data.
23Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
<table border=“1” width=“75%”> <tr> <th>Fruit</th> <th>Color</th> </tr> <tr> <td>Papaya</td> <td>Red</td> </tr> <tr> <td>Banana</td> <td>Yellow</td> </tr></table>
Fruit Color
Papaya Red
Banana Yellow
24Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Create a Table of Phone Numbers
• Suppose that a Member has an arbitrary number of phone numbers (home, work, cell, etc).
• Create an HTML table comprised of the phone numbers. On each row of the table put the type (home, work, cell, etc) in one column and the actual phone number in the next column.
25Copyright (c) [2001]. Roger L. Costello. All Rights Reserved. <?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="html"/>
<xsl:template match="/"> <HTML> <HEAD> <TITLE>Welcome</TITLE> </HEAD> <BODY bgcolor="{/FitnessCenter/Member/FavoriteColor}"> Welcome <xsl:value-of select="/FitnessCenter/Member/Name"/>! <BR/> Your phone numbers are: <TABLE border="1" width="25%"> <TR><TH>Type</TH><TH>Number</TH></TR> <xsl:for-each select="/FitnessCenter/Member/Phone"> <TR> <TD><xsl:value-of select="@type"/></TD> <TD><xsl:value-of select="."/></TD> </TR> </xsl:for-each> </TABLE> </BODY> </HTML> </xsl:template>
</xsl:stylesheet>
(see html-example05)
26Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Iterating through XML Elements
<xsl:for-each select="/FitnessCenter/Member/Phone">
<!- - Within here we are at one of the Phone elements. Thus, in <xsl:value-of select="path", the value for path is relative to where we are in the XML document. The "." refers to the Phone element that we are currently positioned at. - ->
</xsl:for-each>
Do Lab1,Parts 1-3
27Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Special Offer to Platinum Members
• Let's further enhance our example to provide a special offer to "platinum" members.
• We need to check to see if the "level" attribute on the Member element equals "platinum".
28Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
<HTML> <HEAD> <TITLE>Welcome</TITLE> </HEAD> <BODY bgcolor="{/FitnessCenter/Member/FavoriteColor}"> Welcome <xsl:value-of select="/FitnessCenter/Member/Name"/>! <BR/> <xsl:if test="/FitnessCenter/Member/@level='platinum'"> Our special offer to platinum members today is ... <BR/> </xsl:if> Your phone numbers are: <TABLE border="1" width="25%"> <TR><TH>Type</TH><TH>Number</TH></TR> <xsl:for-each select="/FitnessCenter/Member/Phone"> <TR> <TD><xsl:value-of select="@type"/></TD> <TD><xsl:value-of select="."/></TD> </TR> </xsl:for-each> </TABLE> </BODY> </HTML>
(see html-example06)
29Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Conditional Processing
• Use the <xsl:if test="…"/> element to perform conditional processing.
Do Lab1,Part 4
30Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Accessing Multiple Parts of the XML Document
• Let's enhance the table to contain three columns - the name of the Member, the type of the phone (home, work, cell, etc), and the actual phone number.
31Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
<HTML> <HEAD> <TITLE>Welcome</TITLE> </HEAD> <BODY bgcolor="{/FitnessCenter/Member/FavoriteColor}"> Welcome <xsl:value-of select="/FitnessCenter/Member/Name"/>! <BR/> <xsl:if test="/FitnessCenter/Member/@level='platinum'"> Our special offer to platinum members today is ... <BR/> </xsl:if> Your phone numbers are: <TABLE border="1" width="25%"> <TR><TH>Name</TH><TH>Type</TH><TH>Number</TH></TR> <xsl:for-each select="/FitnessCenter/Member/Phone"> <TR> <TD><xsl:value-of select="../Name"/></TD> <TD><xsl:value-of select="@type"/></TD> <TD><xsl:value-of select="."/></TD> </TR> </xsl:for-each> </TABLE> </BODY> </HTML>
(see html-example07)
32Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Getting the Name when accessing the Phone
Member
Phone
555-1234
Phone
555-4321
Name
Jeff
Notice how when in the for-eachloop we need to accessthe Name which is "upand over" with respect to the Phone element
Bottom line: we can access elements in other parts of the XML tree via the “../” operator.
33Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Other ways to Access the XML Data
<xsl:value-of select="/FitnessCenter/Member[1]/Name"/>"Select the Name of the first Member"
<xsl:value-of select="/FitnessCenter/Member[position()=1]/Name"/>"Select the Name of the first Member"
<xsl:value-of select="/FitnessCenter/Member[last()]/Name"/>"Select the Name of the last Member"
<xsl:for-each select="/FitnessCenter/Member[not(position()=last())]"> <!- - Process all Members but the last - -></xsl:for-each>
Note: Assume that there are multiple Members
34Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Other ways to Access the XML Data (cont.)
<xsl:for-each select="/FitnessCenter/Member[position() >1]"> <!- - Process all Members but the first - -></xsl:for-each>
<xsl:for-each select="/FitnessCenter//Name"> <!- - Process all Name elements which have FitnessCenter as an ancestor - -></xsl:for-each>
35Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Enhanced XML Document<?xml version="1.0"?><FitnessCenter> <Member id="1" level="platinum"> <Name>Jeff</Name> <Phone type="home">555-1234</Phone> <Phone type="work">555-4321</Phone> <FavoriteColor>lightgrey</FavoriteColor> </Member> <Member id="2" level="gold"> <Name>David</Name> <Phone type="home">383-1234</Phone> <Phone type="work">383-4321</Phone> <FavoriteColor>lightblue</FavoriteColor> </Member> <Member id="3" level="platinum"> <Name>Roger</Name> <Phone type="home">888-1234</Phone> <Phone type="work">888-4321</Phone> <FavoriteColor>lightyellow</FavoriteColor> </Member></FitnessCenter>
Note that each Membernow has a unique id(the id attribute)
36Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Review - HTML Hyperlinking
<A name="AnnaAndTheKing"></A>
…
<A href="#AnnaAndTheKing">Click Here</A>...
This creates an internal hyperlink (the source "anchor" links tothe target anchor).
37Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Hyperlink Name to Home Phone
• Problem: create an HTML document that has two tables - a Member Name table, and a Member home Phone number table.
• Hyperlink the Member's Name to his/her Phone.
38Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
<TABLE border="1" width="25%"> <TR><TH>Name</TH></TR> <xsl:for-each select="/FitnessCenter/Member"> <TR> <TD> <A href="#{@id}"> <xsl:value-of select="Name"/> </A> </TD> </TR> </xsl:for-each> </TABLE> <BR/><BR/><BR/><BR/><BR/> <TABLE border="1" width="25%"> <TR><TH>Home Phone Number</TH></TR> <xsl:for-each select="/FitnessCenter/Member"> <TR> <TD> <A name="{@id}"> <xsl:value-of select="Phone[@type='home']"/> </A> </TD> </TR> </xsl:for-each> </TABLE>
(see html-example08)
Do Lab1,Parts 5-6
39Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Numbering
• There is an XSL element that returns a number corresponding to the element's position in the set of selected nodes
(see html-example09)
<xsl:for-each select="/FitnessCenter/Member"> <xsl:number value="position()" format="1"/> <xsl:text>. </xsl:text> <xsl:value-of select="Name"/> <BR/></xsl:for-each>
Output:1. Jeff2. David3. Roger
40Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Start Numbering from 0
• How would you start the numbering from zero, rather than one?
<xsl:number value="position() - 1" format="1">
41Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
format attribute of xsl:number
• In the previous example we saw how to generate numbers, and we saw that the generated numbers were 1, 2, 3, etc.
• With the format attribute we can specify the format of the generated number, i.e., 1, 2, 3 or I, II, III, or A, B, C, or …
– format=“1” generates the sequence: 1, 2, 3, …
– format=“01” generates: 01, 02, 03, …
– format=“A” generates: A, B, C, …
– format=“a” generates: a, b, c, …
– format=“I” generates: I, II, III, …
– format=“i” generates: i, ii, iii, ...
42Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
format attribute of xsl:number
<xsl:for-each select="/FitnessCenter/Member"> <xsl:number value="position()" format="A"/> <xsl:text>. </xsl:text> <xsl:value-of select="Name"/> <BR/></xsl:for-each>
Output:A. JeffB. DavidC. Roger
43Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Sorting
• There is an XSL element that sorts the elements that you extract from the XML document
<xsl:for-each select="/FitnessCenter/Member"> <xsl:sort select="Name" order="ascending"/> <xsl:value-of select="Name"/> <BR/></xsl:for-each>
"For each Member, sort the Name elements"
Output:DavidJeffRoger
(see html-example10)
44Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Sorting
<xsl:for-each select="/FitnessCenter/Member"> <xsl:sort select="Name" order="ascending"/> <xsl:value-of select="Name"/> <BR/></xsl:for-each>
The set of Member elements selected by xsl:for-each issorted using the Name child element. This occurs priorto the first iteration of the loop. After the set of Memberelements are sorted then the looping begins.
45Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
concat() function• concat(destination string, string to add)• Note: if you want to concatenate more than one string to the destination string then simply add more arguments
46Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
<xsl:for-each select="/FitnessCenter/Member"> <xsl:value-of select="concat('Welcome ', Name, '!')"/> <BR/></xsl:for-each>
Output:Welcome Jeff!Welcome David!Welcome Roger!
47Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Hello World
xsl:variable
• This XSL element allows you to create a variable to hold a value (which could be a string or a subtree of the XML document).
• The variable is referenced by $variable-name
<xsl:variable name=“hello” select=“'Hello World'”/>
This creates a variable called hello, that has a value which is the literal string, ‘Hello World’.
We could use this variable as follows:
Value = <xsl:value-of select=“$hello”/>
This will output:
Value = Hello World
hello
48Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Member's Phone Numbers: <TABLE border="1" width="25%"> <TR><TH>Name</TH><TH>Type</TH><TH>Number</TH></TR> <xsl:for-each select="/FitnessCenter/Member"> <xsl:variable name="name" select="Name"/> <xsl:for-each select="Phone"> <TR> <TD><xsl:value-of select="$name"/></TD> <TD><xsl:value-of select="@type"/></TD> <TD><xsl:value-of select="."/></TD> </TR> </xsl:for-each> </xsl:for-each></TABLE>
(see html-example12)
49Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
xsl:variable
<xsl:variable name=“member” select=“Member[1]”/>
This creates a variable called member, that has a value which is a subtree.
We could use this variable as follows:
Name = <xsl:value-of select=“$member/Name”/>Home Phone = <xsl:value-of select=“$member/Phone[@type='home']”/>
This will result in generating:
Name = JeffHome Phone = 555-1234
Member
...Name Phone Phone
Jeff 555-1234 555-4321
50Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
xsl:variable
• A variable is “write once, read many”. – That is, you can assign a variable a value only
once, but then you can retrieve the value of the variable many times.
• A variable has a scope limited to the XSL element that it is nested within. Its scope starts where it is defined and extends to the end of the XSL element that it is nested within.
51Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Member's Phone Numbers: <TABLE border="1" width="25%"> <TR><TD>Name</TD><TD>Type</TD><TD>Number</TD></TR> <xsl:for-each select="/FitnessCenter/Member"> <xsl:variable name="name" select="Name"/> <xsl:for-each select="Phone"> <TR> <TD><xsl:value-of select="$name"/></TD> <TD><xsl:value-of select="@type"/></TD> <TD><xsl:value-of select="."/></TD> </TR> </xsl:for-each> </xsl:for-each></TABLE>
The name variable's life ends hereDo Lab2,
Part 1
52Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Global Variables
• You can create a variable outside of <xsl:template match="/">. Then, the variable is global.
<?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="html"/>
<xsl:variable name="pi" select="'3.142857142857'"/>
<xsl:template match="/" > <HTML>
<HEAD> <TITLE>Value of Pi</TITLE> </HEAD> <BODY> The value of pi = <xsl:value-of select="$pi"/> </BODY> </HTML> </xsl:template>
53Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Problem
• Suppose that we want to create a variable, names, and we want this variable to contain a list of the Member Names, with each name separated by a slash. How would you create such a variable?
Here’s what you might attempt to do:
Member's Names:<xsl:variable name="names" select="/FitnessCenter/Member[1]/Name"/><xsl:for-each select="/FitnessCenter/Member[position() > 1]"> <xsl:variable name="names" select="concat($names, '/')"/> <xsl:variable name="names" select="concat($names, Name)"/> </xsl:for-each><xsl:value-of select="$names"/>
Output:
Jeff
(see html-example13)
54Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Let’s add some statements to trace this example
<xsl:variable name="names" select="/FitnessCenter/Member[1]/Name"/><xsl:value-of select="$names"/><BR/><xsl:for-each select="/FitnessCenter/Member[position() > 1]"> <xsl:variable name="names" select="concat($names, '/')"/> <xsl:value-of select="$names"/> <BR/> <xsl:variable name="names" select="concat($names, Name)"/> <xsl:value-of select="$names"/> <BR/> </xsl:for-each> <xsl:value-of select="$names"/>
Output:
JeffJeff/Jeff/DavidJeff/ <--- Why did we loose the previous Name? That name went out of scope.Jeff/RogerJeff
Obviously, this approach doesn’t work. So how do we do it?
(see html-example14)
55Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Here’s what we would like to do
names
Open up thenames box
<xsl:for-each select="/FitnessCenter/Member"> Add this iteration’s Name and a slash to the open names box </xsl:for-each>
Iterate througheach name, adding intothe open box
Jeff/David/RogerClose the box
names
Jeff … / … David … / … Roger
56Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Problem - SolutionIn all previous examples of creating a variable we declared the name of the variable and then had a select attribute which gave the variable its value. We can omit the select attribute:
<xsl:variable name=“names”> - Do stuff in here. All output will go into the names “box”.</xsl:variable>
57Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Problem - Solution
Member's Names:<xsl:variable name="names"> <xsl:value-of select="/FitnessCenter/Member[1]/Name"/> <xsl:for-each select="/FitnessCenter/Member[position() > 1]"> <xsl:text>/</xsl:text> <xsl:value-of select="Name"/> </xsl:for-each></xsl:variable><xsl:value-of select="$names"/>
(see html-example15)
Output:
Member's Names: Jeff/David/Roger
58Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
contains() function
• contains(string to be tested, test string) returns true if string to be tested contains test string
<xsl:if test=“contains($greeting, ‘welcome’)”> $greeting contains ‘welcome’</xsl:if>
Do Lab2,Part 2
59Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
xsl:choose
• xsl:choose allows you to elegantly express multiple conditional tests. Here’s the structure:
<xsl:choose> <xsl:when test='something> [action] </xsl:when> <xsl:when test='something'> [action] </xsl:when> <xsl:otherwise> [action] </xsl:otherwise></xsl:choose>
The first xsl:when statement thatevaluates to true is executed. Ifnone evaluates to true then thexsl:otherwise statement is executed.
60Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
substring-before() String Function
Here’s the form of this string function:
substring-before(string, pattern)
Example:
<xsl:variable name="phone" select="Phone"/><xsl:value-of select="substring-before($phone, '-')"/>
“Get the contents of Phone and put it into the variablecalled ‘phone’. Then extract from the content of ‘phone’ the stringbefore the '-' (i.e., the telephone exchange)”.
555-1234 substring-before($phone, ‘-’) 555phone
61Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
substring-after() String Function
Here’s the form of this string function:
substring-after(string, pattern)
Example:
<xsl:variable name="phone" select="Phone"/><xsl:value-of select="substring-after($phone, '-')"/>
“Get the contents of Phone and put it into the variablecalled ‘phone’. Then extract from the content of ‘phone’ the stringafter the '-'”.
555-1234 substring-after($phone, ‘-’) 1234phone
62Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
starts-with() String Function
Here’s the form of this string function:
starts-with(string, pattern)
Example:
<xsl:if test="starts-with(Phone, '555')"> [action]</xsl:if>
“If the Phone starts with thestring, ‘555’ then do [action]”.
63Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
substring() function
• substring(string, i, len?) returns the substring of string that starts at the ith position and has length, len. The length argument (len) is optional. If not present then this function returns the substring starting at the ith position all the way to the end of the string. Note: the first character is at position 1 (not 0 as with some languages)
substring(‘1234567890’, 2, 5) returns ‘23456’
64Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
string-length() function
• string-length(string) returns the length of the string
string-length(‘1234567890’) returns 10
65Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
translate() function
translate(string, from-pattern, to-pattern)
Example. translate(“Hello”, “ABCDEFGHIJKLMNOPQRSTUVWXYZ”, “abcdefghijklmnopqrstuvwxyz”);
this will convert Hello to hello (i.e., convert to lower case)
A better approach to the above problem is:
<xsl:variable name="upperCaseChars" select=" 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' "/><xsl:variable name="lowerCaseChars" select=" 'abcdefghijklmnopqrstuvwxyz' "/>
translate(“Hello”, $upperCaseChars, $lowerCaseChars)Note: need to put the string within (single) quotes, otherwisethe XSL Processor will try to interpret it as an XML element.
Do Lab2,Part 3
66Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Boolean and Relational Operators
• Boolean operators: not, and, or
• Relational operators: <, >, =, <=, >=, !=
• The less than and greater than signs are reserved symbols, so they need to be escaped when you use them. Thus, the relational operators will appear in your XSL code like this:
< > = <= >= !=< > = <= >= !=
Want this:Use this:
67Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Arithmetic
• The arithmetic operators available: +, -, *, div, mod (remainder from doing a division)– Note: recall that an XML element can have a
dash in the name. So, if you want to indicate subtraction, be sure to surround “-” with blank spaces.
68Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Arithmetic functions
• sum(node set) this function sums up all the values in the set of nodes
• floor(number) returns the largest integer that is not greater than number
– Example. floor(2.5) returns 2
• ceiling(number) returns the smallest integer that is not less than number
– Example. Ceiling(2.5) returns 3
• round(number) returns the integer closest to number
– Example. round(2.3) returns 2
69Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Enhanced XML Document<?xml version="1.0"?><FitnessCenter> <Member id="1" level="platinum"> <Name>Jeff</Name> <Phone type="home">555-1234</Phone> <Phone type="work">555-4321</Phone> <FavoriteColor>lightgrey</FavoriteColor> <MembershipFee>340</MembershipFee> </Member> <Member id="2" level="gold"> <Name>David</Name> <Phone type="home">383-1234</Phone> <Phone type="work">383-4321</Phone> <FavoriteColor>lightblue</FavoriteColor> <MembershipFee>500</MembershipFee> </Member> <Member id="3" level="platinum"> <Name>Roger</Name> <Phone type="home">888-1234</Phone> <Phone type="work">888-4321</Phone> <FavoriteColor>lightyellow</FavoriteColor> <MembershipFee>340</MembershipFee> </Member></FitnessCenter>
Note that each Membernow has MembershipFeeelement
70Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Compute Membership Revenue
Membership Fee Revenue: <xsl:value-of select="sum(/FitnessCenter/Member/MembershipFee)"/>
(see html-example16)
71Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
xsl:attribute
• This XSL element is used by nesting it within an output element. It enables you to create an attribute for the output element
72Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Coloring alternate rows
Member Names:<TABLE border="1" width="25%"> <xsl:for-each select="/FitnessCenter/Member"> <TR> <xsl:if test="position() mod 2 = 0"> <xsl:attribute name="bgcolor">yellow</xsl:attribute> </xsl:if> <TD><xsl:value-of select="Name"/></TD> </TR> </xsl:for-each></TABLE>
(see html-example17)
For each even row of the table, the TR value will be: <TR bgcolor="yellow">
73Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
count() function
count(set of node) returns an integer representing the numberof nodes (i.e., XML elements) in the set.
Example.
Number of members = <xsl:value-of select="count(/FitnessCenter/Member)"/>
Output:Number of members = 5 Do Lab2,
Part 4
74Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Selecting all Elements/Attributes
<xsl:for-each select="/FitnessCenter/Member"> <xsl:for-each select="@*"> ... </xsl:for-each> <xsl:for-each select="*"> ... </xsl:for-each> </xsl:for-each>
For each attribute do ...
For each child elementdo ...
75Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Getting the Name of the Element/Attribute using the
name() Function <xsl:for-each select="/FitnessCenter/Member"> <xsl:for-each select="@*"> Attribute = <xsl:value-of select="name(.)"/> </xsl:for-each> <xsl:for-each select="*"> Element = <xsl:value-of select="name(.)"/> </xsl:for-each> </xsl:for-each>
(see html-example19)
name(node) returns the name of "node"
76Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
When to use Curly Braces?
• “When I assign an attribute a value, when do I use curly braces and when do I not use them?”
Use curly braces for these attributes:- the attribute of a literal result element (where you literally type what should
be output)Example: <a href=“#{@id}”>
- the name attribute of xsl:attributeExample: <xsl:attribute name =“{@value}”>
- the name attribute of xsl:piExample: <xsl:pi name =“{@value}”>
- the name attribute of xsl:elementExample: <xsl:element name =“{@value}”>
- the optional attributes of xsl:sort:Example: <xsl:sort order =“{@value}”>
lang =“{@value}”>data-type =“{@value}”>case-order =“{@value}”>
77Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
document( ) Function
• This function enables you to access other XML documents (besides the XML document that you specify when you invoke the XSL Processor).
• The format for using the document() function is: document(url), where url is a URL to another XML document
78Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Fitness Centers Merger
• Another fitness center has just merged with us. They have an xml document (FitnessCenter2.xml) containing their Members.
• You are to create an XSL-enhanced HTML document that creates a single table comprised of all the Members from both fitness clubs.
79Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
<TABLE border="1" width="75%"> <TR><TH>Name</TH><TH>Phone(home)</TH>...</TR> <xsl:for-each select="/FitnessCenter/Member"> <TR> <TD><xsl:value-of select="Name"/></TD> <TD><xsl:value-of select="Phone[@type='home']"/></TD> <TD><xsl:value-of select="Phone[@type='work']"/></TD> <TD><xsl:value-of select="FavoriteColor"/></TD> </TR> </xsl:for-each> <xsl:variable name="FitnessCenter2" select="document('file://localhost/xml-course/.../FitnessCenter2.xml')"/> <xsl:for-each select="$fitnessCenter2/FitnessCenter/Member"> <TR> <TD><xsl:value-of select="Name"/></TD> <TD><xsl:value-of select="Phone[@type='home']"/></TD> <TD><xsl:value-of select="Phone[@type='work']"/></TD> <TD><xsl:value-of select="FavoriteColor"/></TD> </TR> </xsl:for-each></TABLE>
(see html-example20)
Do Lab3,Part 1
80Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Parameterized Processing
• You can create a subroutine (called a named template), and you can pass to it parameters.
81Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
<xsl:template match="/"> <HTML> <HEAD> <TITLE>Fitness Center</TITLE> </HEAD> <BODY> <xsl:call-template name="displayNameWithFont"> <xsl:with-param name="fontFace" select="'Impact'"/> <xsl:with-param name="name" select="/FitnessCenter/Member[1]/Name"/> </xsl:call-template> <BR/> ... </BODY> </HTML> </xsl:template>
<xsl:template name="displayNameWithFont"> <xsl:param name="fontFace" select="'Braggadocio'"/> <!-- default font --> <xsl:param name="name"/> <FONT face="{$fontFace}"> <xsl:value-of select="$name"/> </FONT> </xsl:template>
(see html-example21)
82Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Call by Reference
• How do we create a named template that returns a value?
• Example: create a named template which, when passed a number, it returns the number div 2.
83Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
<xsl:template match="/"> <HTML> <HEAD> <TITLE>Fitness Center</TITLE> </HEAD> <BODY> 16 / 2 = <xsl:variable name="result"> <xsl:call-template name="NumDiv2"> <xsl:with-param name="N" select="16"/> </xsl:call-template> </xsl:variable> <xsl:value-of select="$result"/> </BODY> </HTML> </xsl:template>
<xsl:template name="NumDiv2"> <xsl:param name="N"/> <xsl:value-of select="$N div 2"/> </xsl:template>
(see html-example22)Do Lab3,
Part 2
84Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
generate-id()
• Use this function to generate a unique string for a node
Example. generate-id(/FitnessCenter/Member[1]) will return a unique id for the first Member
85Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
Using generate-id() to Uniquely Identify Elements
• In html-example08 we created two tables - a table containing the Members Names, and a separate table containing home Phone numbers. Each Name was hyperlinked to his/her home Phone. We used the id attribute on each Member element to link the two tables together.
• Suppose there is no id attribute. We can use generate-id() to create a unique identifier.
86Copyright (c) [2001]. Roger L. Costello. All Rights Reserved.
<TABLE border="1" width="25%"> <TR><TH>Name</TH></TR> <xsl:for-each select="/FitnessCenter/Member"> <TR> <TD> <A href="#{generate-id(.)}"> <xsl:value-of select="Name"/> </A> </TD> </TR> </xsl:for-each> </TABLE> <BR/><BR/><BR/><BR/><BR/> <TABLE border="1" width="25%"> <TR><TH>Home Phone Number</TH></TR> <xsl:for-each select="/FitnessCenter/Member"> <TR> <TD> <A name="{generate-id(.)}"> <xsl:value-of select="Phone[@type='home']"/> </A> </TD> </TR> </xsl:for-each> </TABLE>
(see html-example23)