1.34k likes | 1.48k Views
Introduction to XSLT. Cheng-Chia Chen. XSL. XSL Processor. XML. HTML (or XML or text). What is XSLT ?. XSLT is a language for transforming XML documents into other [XML] documents . XML syntax Possible output formats: XML HTML TEXT. Outlines.
E N D
Introduction to XSLT Cheng-Chia Chen
XSL XSL Processor XML HTML (or XML or text) What is XSLT ? • XSLT is a language for transforming XML documents into other [XML] documents. • XML syntax • Possible output formats: • XML • HTML • TEXT
Outlines • Transform XML Documents into HTML Documents • Transform XML Documents into other XML Documents • Transform XML Documents into Texts. Note: Most slide materials adapted from Roger L. Costello
HTML Generation • Use XSL to generate HTML documents. • XSLT viewed as a tool to fill in the content of an HTML document with data extracted from an XML Document. • XSLT provides elements (tags) for extracting the XML data
XML Document HTML Document (with embedded XSL elements) XSL element XML data Enhancing HTML Documents with XML Data
Enhancing HTML Documents with the Following XML Data <?xml version="1.0"?> <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
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> Literal result elements are elements in templates not from xsl namespace. htmlEx1
Note • The HTML is embedded within an XSL template, which is an XML document. Consequently, • the embedded HTML must be well formed, • e.g., every start tag must have an end tag • We can add XSL elements to the embedded HTML, which allows us to extract data out of XML documents.
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> htmlEx2
Extracting a Value from an XML Document,Navigating the XML Document • Extracting values: • use the <xsl:value-of select="…"/> XSL element • Navigating: • … is an XPath expression with matched node as context node. • Recall what the location path : • /FitnessCenter/Member/Name • means: • "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."
The tree view of fitnessCenter.xml Document / PI <?xml version=“1.0”?> Element FitnessCenter ... Element Member Element Member Element Member ... ... Element Phone Element Name Element FavoriteColor Element Phone Text 555-4321 Text Jeff Text lightgrey Text 555-1234
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> htmlEx3
Notes • Attribute values cannot contain "<" nor ">“ • 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 attribute value you must use curly braces: <Body bgcolor="{/FitnessCenter/Member/FavoriteColor}"> Evaluate the expression within the curly braces. Assign the value to the attribute. The place of an attribute value where we can put xpath expr within curly braces is called an attribute value template(avt).
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> htmlEx4
Note In this example we want "the Phone element where the value of its type attribute equals 'home' ": <xsl:value-of select="/FitnessCenter/Member/Phone[@type='home']"/> The expression within […] is called a "predicate". Its purpose is to filter. Note the use of the single quotes within the double quotes. select=" … ' …' …"
<table border=“1” width=“100%”> <th> </th> <th> </th> <th> </th> </tr> <tr> <td> </td> <td> </td> <td> </td> </tr> <tr> <td> </td> <td> </td> <td> </td> <tr> </tr> </table> Review - HTML Table This will create a table with 3 rows - the first row contains a header for each column. The next two rows contains the table data.
<table border=“1” width=“75%”> <tr> <th>Fruit</th> <th>Color</th> </tr> <tr> <td>Apple</td> <td>Red</td> </tr> <tr> <td>Banana</td> <td>Yellow</td> </tr> </table> Fruit Color Red Apple Yellow Banana
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.
<?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> context node is the currently processed phone node htmlEx5
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>
Special Offer to Platinum Members • Enhance the example to provide a special offer to "platinum" members. • We need to checkif the "level" attribute on the Member element equals "platinum".
<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> htmlEx6
Conditional Processing • Use the <xsl:if test="…“> IfTruePart <…/> element to perform conditional processing. • Note: It is needless to add in the value of test attribute extra { and }, which must appear in <Body bgcolor="{/FitnessCenter/Member/FavoriteColor}">
Accessing Multiple Parts of the XML Document • 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.
<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> htmlEx7
Member Notice how we access the Name with respect to the Phone element Via the location path ../Name Phone Name Phone 555-1234 Jeff 555-4321 Getting the Name when accessing the Phone .. Name • We can access elements in other parts of the XML tree via the “../” operator.
Other ways to Access the XML Data Note: Assume that there are multiple Members <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(last())]"> <!- - Process all Members but the last - -> </xsl:for-each>
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>
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 Member now has a unique id (the id attribute) fitnessCenter-2.xml
Review - HTML Hyperlinking <A name="Anchor2" /> … <A href="#Anchor2">Click Here</A> ... This creates an internal hyperlink (the source anchor links to the target anchor).
Hyperlink Name to Home Phone Problem: 1. create an HTML document that has two tables: - a Member Name table, and - a Member home Phone number table. 2. Hyperlink the Member's Name to his/her Phone.
<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> htmlEx8
Numbering • There is an XSL element that returns a number corresponding to the element's position in the set of selected nodes <xsl:for-each select="/FitnessCenter/Member"> <xsl:numbervalue="position()"format="1"/> <xsl:text>.</xsl:text> <xsl:value-of select="Name"/> <BR/> </xsl:for-each> Output: 1. Jeff 2. David 3. Roger htmlEx9
Start Numbering from 0 • How would you start the numbering from zero, rather than one? <xsl:number value="position() - 1" format="1">
format attribute of xsl:number • 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 A.1, A.2, A.3, 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, ...
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. Jeff B. David C. Roger
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> Output: David Jeff Roger "For each Member, sort the Name elements" htmlEx10
Sorting <xsl:for-each select="/FitnessCenter/Member"> <xsl:sort select="Name" order="ascending"/> <xsl:value-of select="Name"/> <BR/> </xsl:for-each> Note: 1. Sort occurs before iteration. 2. I.e. The set of Member elements selected by xsl:for-each is sorted using the Name child element. This occurs prior to the first iteration of the loop.. After the set of Member elements are sorted then the looping begins
concat() function • concat(destination string, strings to add) • Note: if you want to concatenate more than one string to the destination string then simply add more arguments
<xsl:for-each select="/FitnessCenter/Member"> <xsl:value-of select="concat('Welcome ', Name, '!')"/> <BR/> </xsl:for-each> Output: Welcome Jeff! Welcome David! Welcome Roger! htmlEx11
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
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> htmlEx12
Member ... Phone Phone Name Jeff 555-1234 555-4321 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 = Jeff Home Phone = 555-1234
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 declaration is visible to the following siblings and its descendants. • This region is the scope of the variable binding.
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 scope
Global Variables • Are variables declared outside of template elements <xsl:template match="/">. <?xml version="1.0"?> <xsl:stylesheet mlns: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> …</xsl:stylesheet>
Problem • Create a variable, names, to contain a list of the Member Names, with each name separated by a slash. • How would you create such a variable? First attempt: 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: A parameter or variable with the same name already exists in the current scope. htmlEx13
Problem - Solution In 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>
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"/> Output: Member's Names: Jeff/David/Roger htmlEx15