XPath tutorial - basics: Difference between revisions

The educational technology and digital learning wiki
Jump to navigation Jump to search
 
m (Text replacement - "<pageby nominor="false" comments="false"/>" to "<!-- <pageby nominor="false" comments="false"/> -->")
 
(48 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{Incomplete}}
{{Incomplete}}
<pageby nominor="false" comments="false"/>
{{web technology tutorial|Intermediate}}
<!-- <pageby nominor="false" comments="false"/> -->
 
== Introduction ==
== Introduction ==


==== Prerequisites ====
XPath is a language for addressing parts of an XML document. Basic understanding of XPath is needed for [[XSLT]] and [[XQuery]] programming. In this piece, we shall show how to create XSLT stylesheets that use some moderately complex XPath expressions
 
Tip: Read the free O'Reilly book: http://commons.oreilly.com/wiki/index.php/XPath_and_XPointer


* Editing XML (being able to use a simple DTD)
<div class="tut_goals">
* Introductory XSLT (xsl:template, xsl:apply-templates and xsl:value-of)
* Know about the role of XPath with respect to XSLT


==== Objectives ====
'''Learning Objectives '''


* Better understand XPath expressions
* Understand how to use XPath expressions, in order use XSLT and XQuery more effectively
* Learn some XSLT programming constructions (conditions and loops)
* Learn some XSLT programming constructions (conditions and loops)
* Being able to cope with most XML to HTML transformations
* Being able to cope with most XML to HTML transformations


==== Disclaimer ====
''' Prerequisites '''
 
* [[Editing XML tutorial]] (being able to use a simple DTD).
* [[XSLT Tutorial - Basics]], introductory XSLT (xsl:template, xsl:apply-templates and xsl:value-of)


''' Next steps '''
* [[XSLT to generate SVG tutorial]]
* [[XQuery tutorial - basics]]
'''Materials'''
* We use the same XML document in most examples. You can download the file or look at a wiki page:
: [http://tecfa.unige.ch/guides/xml/examples/xpath/xpath-jungle.xml xpath-jungle.xml]
: [[XPath tutorial - basics/XML example code]]
* Directory: http://tecfa.unige.ch/guides/xml/examples/xpath/
</div>
''' Disclaimer '''
* This is an unfinished, not very nice, introductory [[XPath]] tutorial. Cut/paste from slides with a few fixes. It needs more work, since right now it's more like a list of XPath features ... - [[User:Daniel K. Schneider|Daniel K. Schneider]]
* There may be typos (sorry) and mistakes (sorry again)
* There may be typos (sorry) and mistakes (sorry again)
* Please also consult a textbook !


== Introduction to XML Path Language ==
== Introduction to XML Path Language ==
Line 24: Line 42:
=== Definition and history ===
=== Definition and history ===


* XPath is a language for addressing parts of an XML document
XPath is a language for addressing parts of an XML document, In support of this primary purpose, it also provides basic facilities for manipulation of strings, numbers and booleans.
* In support of this primary purpose, it also provides basic facilities for manipulation of strings, numbers and booleans.
 
Its 2.0 editition was described as {{quotation|XPath 2.0 is an expression language that allows the processing of values conforming to the data model defined in [http://www.w3.org/TR/xpath-datamodel/ XQuery/XPath Data Model (XDM)]. The data model provides a tree representation of XML documents as well as atomic values such as integers, strings, and booleans, and sequences that may contain both references to nodes in an XML document and atomic values. The result of an XPath expression may be a selection of nodes from the input documents, or an atomic value, or more generally, any sequence allowed by the data model. The name of the language derives from its most distinctive feature, the path expression, which provides a means of hierarchic addressing of the nodes in an XML tree.}} ([http://www.w3.org/TR/xpath20/ XML Path Language (XPath) 2.0]
,W3C Recommendation 23 January 2007, retrieved 16:38, 9 February 2010 (UTC).
 
* XPath uses a compact non-XML syntax (to facilitate use of XPath within URIs and XML attribute values).
* XPath uses a compact non-XML syntax (to facilitate use of XPath within URIs and XML attribute values).
* XPath gets its name from its use of a path notation as in URLs for navigating through the hierarchical structure of an XML document.
* XPath gets its name from its use of a path notation as in URLs for navigating through the hierarchical structure of an XML document.
* XPath was defined at the same time as XSLT (nov 1999)
* XPath was defined at the same time as XSLT (nov 1999)
* Initally, it was developped to support XSLT and XPointer (XML Pointer Language used for XLink, XInclude, etc.)
* Initally, it was developped to support XSLT and XPointer (XML Pointer Language used for XLink, XInclude, etc.). Today it is also used by XQuery and other applications. Many programming languages support an XPath library, e.g. PHP5.
 
In plain English, XPath allows retrieving parts of an XML document. XPath expressions can be as simple as the name of an XML element or so complicated that only experts can understand it ....


; Specifications
; Specifications
* XPath 1.0 '' http://www.w3.org/TR/xpath'' (nov 1999)
* XPath 1.0 (nov 1999) (http://www.w3.org/TR/xpath)
** Used by XSLT 1.0
* XPath 2.0 (Jan 2007) (http://www.w3.org/TR/xpath20/)
* XPath 2.0 '' http://www.w3.org/TR/xpath20/'' (Jan 2007)
* XPath 2.0 Functions and Operators http://www.w3.org/TR/xquery-operators/
* XPath 2.0 Functions and Operators '' http://www.w3.org/TR/xquery-operators/''
* XQuery 1.0 and XPath 2.0 Data Model (XDM) http://www.w3.org/TR/xpath-datamodel/
** XPath 2.0 is a superset of XPath 1.0
** Used by XSLT 2.0 and XQuery ... and other specifications
 
=== XSLT, XQuery and XPath ===


* Each time a given XSLT or XQuery instruction needs to address (refer to) parts of an XML document we use XPath expressions.
XPath 1.0 is used by XSLT 1.0, i.e. the XSLT processor included in virtually every web browser as of Jan 2010 and since the early 2000's in IE/Mozilla.
* XPath expressions also can contain functions, simple math and boolean expressions
* Typically, XPath expressions are used in'' match'' , '' select '' and '' test'' attributes


[[Image:xml-xpath-2.png]]
XPath 2.0 is a superset of XPath 1.0 and is used by XSLT 2.0, [[XQuery]] and other specifications.


== 2. The XPath Syntax and the document model ==
; Reference manuals
* [https://developer.mozilla.org/en/Transforming_XML_with_XSLT Transforming XML with XSLT] (includes a useful overview of XSLT/XPath functions)


=== 2.1 Xpath Syntax ===
=== XSLT, XQuery and XPath ===


===== Primary (relatively simple) XPath expressions: =====
Each time a given XSLT or XQuery instruction needs to address (refers to) parts of an XML document, we use XPath expressions. XPath expressions also can contain functions, simple math and boolean expressions.


[[Image:xml-xpath-3.png]]
Within [[XSLT]], XPath expressions are typicially used in ''match'', ''select'' and ''test'' attributes:


[[Image:xml-xpath-2.png|frame|none|Xpath expressions in an XSLT template]]


Below is an XQuery example taken from the [[XQuery tutorial - basics]]


===== Result of an Xpath =====
<source lang="java">
for $t in fn:doc("catalog09.xml")//c3msbrick
let $n := count($t//c3mssoft)
where ($n > 1)
order by $n
return <result> {$t/title/text()} owns {$n} bricks </result>
</source>


* Can be various things, e.g. sets of nodes, a single node, a number, etc ....
=== Playtime ===


Most XML editors will display the XPath of a selected element.
In addition, you can search with XPath expressions, i.e. test an expression that you then would use in your XSLT or XQuery code.


Below is a screenshot of the XML Exchanger editor. As you can see we entered the ''//participant'' expression in the search box. The result is a so-called '''node-set''' that is displayed in the XPath pane at the bottom.


===== There are two notations for location paths =====
[[Image:xngr-editor-xpath.png|thumb|800px|none|Xpath seach in the Exchanger editor]]


# abbreviated (less available options)
== The XPath Syntax and the document model ==
#* e.g. '' para'' is identical to '' child::para''
# unabbreviated (not presented in these slides !!)
#* e.g. "'' child::para'' " would define the '' para'' element children of the current context node.


=== Xpath Syntax ===


XPath expressions can be quite simple or very complex. An Xpath expression may include a '''location path''' (i.e. "where to look for"), '''node tests''' (i.e. identifying a node) and '''predicates'''(i.e. additional tests).


===== The formal specification of an XML Path =====
There are two notations for location paths.


** is very complex, i.e. has about 39 clauses and is very difficult to understand
'''(1) abbreviated '''
** Some expressions shown here are beyound the scope of this class, don���%G�₁��%@���t panic !


This simple notation allows to locate itself, children, parents, attributes and combinations of these. Going up or down is called an '''axis'''. The abbreviated form has limited axis.
:''para'' means "all "para" child elements of the current context


'''(2) unabbreviated'''


=== 2.2 The document model of XPath ===
Unabbreviated location path allows to search in more axis then just parents, children, and siblings.


* XPath sees an XML document as a tree structure
:''child::para''" is identical to ''para'' above.
* Each information (XML elements, attributes, text, etc.) is called a '' node''
** this is fairly similar to the W3C DOM model an XML or XSLT processor would use


The abbreviated location path look a bit like file paths. E.g. the following expression:
/section/title
means: find all title nodes below section nodes


'''Syntax overview of the primary (relatively simple) XPath expressions'''


===== Nodes that XPath can see: =====
The picture below is not entirely correct, i.e. the "green" elements are part of the so called node-test
[[Image:xml-xpath-3.png]]


* root node
The result of an Xpath expression can be various data types, e.g. sets of nodes, a single node, a number, etc. Most often the result, is a set of nodes.
** ATTENTION: The root is not necessarily the XML root element. E.g. processing instructions like a stylesheet declaration are also nodes.
* Elements and attributes
* Special nodes like comments, processing instructions, namespace declarations.




;The formal specification of an XML Path


===== Nodes XPath can���%G�₁��%@���t see: =====
* is very complex, i.e. has about 39 clauses and is very difficult to understand
* Some expressions shown here are beyond the scope of this tutorial, don't panic !


* XPath looks at the final document, therefore can���%G�₁��%@���t see entities and document type declarations....
=== The document model of XPath ===


* XPath sees an XML document as a tree structure
* Each information (XML elements, attributes, text, etc.) is called a '' node''. This is fairly similar to the W3C DOM model an XML or XSLT processor would use.


;Nodes that XPath can see:


===== The XML context =====
* root node
** ATTENTION: The root is not necessarily the XML root element. E.g. processing instructions like a stylesheet declaration are also nodes.
* Elements and attributes
* Special nodes like comments, processing instructions, namespace declarations.


* What a given XPath expression means, is always defined by a given XML context, i.e. the current node in the XML tree
;Nodes XPath can't see:


* XPath looks at the final document, therefore it can't see entities and document type declarations....


;The XML context


===== ... Advance warning: =====
* What a given XPath expression means, is always defined by a given XML context, i.e. the current node in the XML tree a processor is looking at.


The rest of this chapter will be quite boring (and it only covers XPath essentials ....)
== Using simple location path ==


Below, we present a few expressions for locating nodes using the simple abbreviated syntax. As we said before, location paths can be horribly complex, but simple location path look a bit like file path that you would use in HTML links or in an operating system like Unix, Windows or MacOS.


=== List of simple location path ===


=== 2.3 Element Location Paths ===
; Document root node - returns the document root (which is not necessarily the XML root!)
: ''/''


* We present a few expressions for locating nodes
; Direct child element:
* This page is not complete and uses abbreviated syntax
:''XML_element_name''


; Direct child of the root node:
:''/XML_element_name''


; Child of a child:
:''XML_element_name/XML_element_name''


==== Document root node: returns the document root (which is not necessarily the XML root!) ====
; Descendant of the root:
:''//XML_element_name''


/
; Descendant of a node:
:''XML_element_name//XML_element_name ''


; Parent of a node:
:''../ ''


; A far cousin of a node:
:''../../XML_element_name/XML_element_name/XML_element_name''


==== Direct child element: ====
=== Example - Extracting titles from an XML file with XSLT ===


'' XML_element_name''
Let us recall that we use the same XML document in most examples. You can download the file or look at a wiki page:
: [http://tecfa.unige.ch/guides/xml/examples/xpath/xpath-jungle.xml xpath-jungle.xml]
: [[XPath tutorial - basics/XML example code]]


<source lang="XML">


<?xml version="1.0"?>
<project>
<title>The Xpath project</title>
<participants>
  <participant>
    <FirstName>Daniel</FirstName>
    <qualification>8</qualification>
    <description>Daniel will be the tutor</description>
    <FoodPref picture="dolores_001.jpg">Sea Food</FoodPref>
  </participant>
  <participant>
    <FirstName>Jonathan</FirstName>
    <qualification>5</qualification>
    <FoodPref picture="dolores_002.jpg">Asian</FoodPref>
  </participant>
  <participant>
  <FirstName>Bernadette</FirstName>
  <qualification>8</qualification>
    <description>Bernadette is an arts major</description>
  </participant>
  <participant>
  <FirstName>Nathalie</FirstName>
  <qualification>2</qualification>
  </participant>
</participants>
<problems>
  <problem>
    <title>Initial problem</title>
    <description>We have to learn something about Location Path</description>
    <difficulty level="5">This problem should not be too hard</difficulty>
  </problem>
  <solutions>
  <item val="low">Buy a XSLT book</item>
  <item val="low">Find an XSLT website</item>
  <item val="high">Register for a XSLT course and do exercices</item>
  </solutions>
  <problem>
    <title>Next problem</title>
    <description>We have to learn something about predicates</description>
    <difficulty level="6">This problem is a bit more difficult</difficulty>
  </problem>
  <solutions>
  <item val="low">Buy a XSLT book</item>
  <item val="medium">Read the specification and do some exercises</item>
  <item val="high">Register for a XPath course and do exercices</item>
  </solutions>
</problems>
</project>
</source>


==== Direct child of the root node: ====
;Task


'' /XML_element_name''
We would like to get a simple list of problem titles


; Solution


XSLT template (file: [http://tecfa.unige.ch/guides/xml/examples/xpath/xpath-jungle-1.xsl xpath-jungle-1.xsl]
<source lang="XML">
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">


==== Child of a child: ====
  <xsl:output method="html"/>


'' XML_element_name/XML_element_name''
  <xsl:template match="/project">
    <html>
      <body bgcolor="#FFFFFF">
        <h1><xsl:value-of select="title" /></h1>
        Here are the titles of our problems: <ul>
        <xsl:apply-templates select="problems/problem" />
      </ul>
      </body>
    </html>
  </xsl:template>


<xsl:template match="problems/problem">
  <li><xsl:value-of select="title" /></li>
</xsl:template>


</xsl:stylesheet>
</source>


==== Descendant of the root: ====
; (1) XSLT template for the root element


'' //XML_element_name''
* The XPath of the "match" means: apply the template to the ''project'' element node, which is a direct child of the root node
* The ''execution context'' of this template is therefore the element "''project''"
* The ''xsl:apply-templates'' expression will now tell the processor to find a rule for the ''problems/problem'' descendant.


;(2) XSLT template for the problems/problem element


This second rule will be triggered by the first rule, because ''problems/problem'' is indeed a location that can be found in project element. The processor then can extract the value of the ''title'' element.


==== Descendant of a node: ====
Alternatively we could have written this rule as:
 
<source lang="XML">
'' XML_element_name//XML_element_name ''
<xsl:template match="problems/problem/title">
 
  <li><xsl:apply-templates/></li>
 
</xsl:template>
 
</source>
==== Parent of a node: ====
or
 
<source lang="XML">
'' ../ ''
<xsl:template match="problems/problem/title">
 
  <li><xsl:value-of select="."/></li>
 
</xsl:template>
 
</source>
==== Un far cousin of a node: ====
 
'' ../../XML_element_name/XML_element_name/XML_element_name''
 
 
 
==== Example 2-1: Extracting titles from an XML file ====
 
 
 
===== An XML document (file: xpath-jungle.xml used throughout the XPath chapter) =====
 
* We only show part of the document
 
<nowiki>!-- XML fragment --&gt;</nowiki>
 
&lt;'' project'' &gt;
 
'' '' &lt;title&gt;The Xpath project&lt;/title&gt;
 
......
 
&lt;problems&gt;
 
'' &lt;problem&gt;''
 
'' &lt;title&gt;'' Initial problem'' &lt;/title&gt;''
 
&lt;description&gt;We have to learn something about Location Path&lt;/description&gt;
 
&lt;difficulty level="5"&gt;This problem should not be too hard&lt;/difficulty&gt;
 
'' &lt;/problem&gt;''
 
'' &lt;problem&gt;''
 
'' &lt;title&gt;'' Next problem'' &lt;/title&gt;''
 
&lt;description&gt;We have to learn something about predicates&lt;/description&gt;
 
&lt;difficulty level="6"&gt;This problem is a bit more difficult&lt;/difficulty&gt;
 
'' &lt;/problem&gt;''
 
&lt;/problems&gt;
 
&lt;/project&gt;
 
 
 
===== Task =====
 
* We would like to get a simple list of problem titles
 
(XSLT Templates on next slide)
 
 
 
===== (1) XSLT template for project XML root element (file: xpath-jungle-1.xsl) =====
 
&lt;xsl:template match="'' /project'' "&gt;
 
&lt;html&gt;
 
&lt;body bgcolor="#FFFFFF"&gt;
 
&lt;h1&gt;&lt;xsl:value-of select="title" /&gt;&lt;/h1&gt;
 
Here are the titles of our problems:
 
&lt;ul&gt;
 
&lt;xsl:apply-templates select="'' problems/problem'' " /&gt;
 
&lt;/ul&gt;
 
&lt;/body&gt;
 
&lt;/html&gt;
 
&lt;/xsl:template&gt;
 
* The XPath of the "match" means: applies to '' project'' element node, descendant of root node
* Execution '' context'' of this template is therefore the element "'' project'' "
* xsl:apply-templates will select a rule for descendant "'' problem'' ".
 
 
 
===== (2) XSLT template for the problem element =====
 
&lt;xsl:template match='' "'' '' problems/problem'' '' "'' &gt;
 
&lt;li&gt;&lt;xsl:value-of select="'' title'' " /&gt;&lt;/li&gt;
 
&lt;/xsl:template&gt;
 
* This second rule will be triggered by the first rule, because problems/problem is indeed a descendant of the project element
 
 
 
===== (3) Result HTML =====
 
&lt;html&gt;
 
    &lt;body bgcolor="#FFFFFF"&gt;
 
      &lt;h1&gt;The Xpath project&lt;/h1&gt;


;(3) Result HTML
<source lang="XML">
<html>
    <body bgcolor="#FFFFFF">
      <h1>The Xpath project</h1>
       Here are the titles of our problems:
       Here are the titles of our problems:
      <ul>
          ''<li>Initial problem</li>''
          ''<li>Next problem</li>''
      </ul>
    </body>
</html>
</source>


      &lt;ul&gt;
Live example:
 
* [http://tecfa.unige.ch/guides/xml/examples/xpath/xpath-jungle-1.xml xpath-jungle-1.xml]
          ''&lt;li&gt;Initial problem&lt;/li&gt;''
 
''        &lt;li&gt;Next problem&lt;/li&gt;''


      &lt;/ul&gt;
=== Attribute Location Paths ===


    &lt;/body&gt;
Of course, XPath also also to locate attributes. We shall show the principle, using a few examples.


&lt;/html&gt;
(1) To find an attribute of a child element in the current context use:


 
:''@attribute_name''
 
=== 2.4 Attribute Location Paths ===
 
 
 
==== Find an attribute of a child element of the current context ====
 
'' @attribute_name''


Example:
Example:
: @val


@val
(2) Find attributes of an element in a longer location path starting from root
 
 


==== Find attributes of an element in a longer location path starting from root ====
''/element_name/element_name/@attribute_name''
 
'' /element_name/element_name/@attribute_name''


Example:
Example:
  /project/problems/solutions/item/@val
  /project/problems/solutions/item/@val


 
(3) Find attributes in the whole document:
 
==== Find attributes in the whole document ====
 
'' //@attribute_name''
'' //@attribute_name''


As you can see you can combine element location with attribute identification.


=== Example - Create an html img link from an attribute ===


==== Example 2-2: Make an html img link from an attribute ====
;XML fragment
 
Same as above
 
 
===== XML fragment =====
 
&lt;participants&gt;
 
  &lt;participant&gt;
 
    &lt;FirstName&gt;Daniel&lt;/FirstName&gt;
 
    &lt;qualification&gt;8&lt;/qualification&gt;
 
    &lt;description&gt;Daniel will be the tutor&lt;/description&gt;
 
    &lt;FoodPref picture="dolores_001.jpg"&gt;Sea Food&lt;/FoodPref&gt;
 
  &lt;/participant&gt;
 
  &lt;participant&gt;
 
    &lt;FirstName&gt;Jonathan&lt;/FirstName&gt;
 
    &lt;qualification&gt;5&lt;/qualification&gt;
 
    &lt;FoodPref picture="dolores_002.jpg"&gt;Asian&lt;/FoodPref&gt;
 
  &lt;/participant&gt;
 
  &lt;participant&gt;
 
    &lt;FirstName&gt;Bernadette&lt;/FirstName&gt;
 
    &lt;qualification&gt;8&lt;/qualification&gt;
 
    &lt;description&gt;Bernadette is an arts major&lt;/description&gt;
 
  &lt;/participant&gt;
 
  .......
 
 
 
===== Task =====
 
* Display a list of First Names plus their food preferences
 


;Task
Display a list of First Names plus their food preferences


===== XSLT (File xpath-jungle-2.xsl) =====
;XSLT (File [http://tecfa.unige.ch/guides/xml/examples/xpath/xpath-jungle-2.xsl xpath-jungle-2.xsl]


* The first rule will just select all participants and create the list container (ul)
<source lang="XML">
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">


   &lt;xsl:template match="/"&gt;
   <xsl:output method="html"/>


    &lt;html&gt;
  <xsl:template match="/">
    <html>
      <body bgcolor="#FFFFFF">
        <h1>What do we know about our participants ?</h1>
        Here are some food preferences: <ul>
        <xsl:apply-templates select=".//participant" />
      </ul>
      </body>
    </html>
  </xsl:template>


      &lt;body bgcolor="#FFFFFF"&gt;
<xsl:template match="participant">
  <li><xsl:value-of select="FirstName"/>
  <xsl:apply-templates select="FoodPref"/>
  </li>
</xsl:template>


        &lt;h1&gt;What do we know about our participants ?&lt;/h1&gt;
<xsl:template match="FoodPref">
  prefers <xsl:value-of select="."/>.
  <img src="{@picture}"/> <br clear="all"/>
</xsl:template>


        Here are some food preferences:
</xsl:stylesheet>


''        &lt;ul&gt;''
</source>
 
        &lt;xsl:apply-templates select=''".//participant"''
  /&gt;
 
      ''  &lt;/ul&gt;''
 
      &lt;/body&gt;
 
    &lt;/html&gt;
 
  &lt;/xsl:template&gt;


* The second rule will display names of participants and launch a template for FoodPref
* The second rule will display names of participants and launch a template for FoodPref
* Note: Not all participants have a FoodPref element. If it is absent it will just be ignored.
* Note: Not all participants have a FoodPref element. If it is absent it will just be ignored.
* The third rule (FoodPref) displays the text (contents) of FoodPref and then makes an HTML img tag


&lt;xsl:template match="participant"&gt;
  &lt;li&gt;&lt;xsl:value-of select="''FirstName''
"/&gt;
  &lt;xsl:apply-templates select="''FoodPref''
"/&gt;
  &lt;/li&gt;
&lt;/xsl:template&gt;
* This rule displays the text (contents) of FoodPref and then makes an HTML img tag
&lt;xsl:template match="FoodPref"&gt;
  prefers &lt;xsl:value-of select=''"."''
/&gt;.
  &lt;img src="''{@picture}''
"/&gt; &lt;br clear="all"/&gt;
&lt;/xsl:template&gt;
===== Parts of the result: =====
  &lt;h1&gt;What do we know about our participants ?&lt;/h1&gt;


;Parts of the result:
<source lang="xml">
  <h1>What do we know about our participants ?</h1>
       Here are some food preferences:
       Here are some food preferences:
 
       <ul>
       &lt;ul&gt;
           <li>Daniel prefers Sea Food.
 
             <img src="dolores_001.jpg"><br clear="all"></li>
           &lt;li&gt;Daniel prefers Sea Food.
           <li>Jonathan
 
             &lt;img src="dolores_001.jpg"&gt;&lt;br clear="all"&gt;&lt;/li&gt;
 
           &lt;li&gt;Jonathan
 
             prefers Asian.
             prefers Asian.
            <img src="dolores_002.jpg"><br clear="all"></li>
          <li>Bernadette</li>
          <li>Nathalie</li>
      </ul>
</source>


            &lt;img src="dolores_002.jpg"&gt;&lt;br clear="all"&gt;&lt;/li&gt;
Live example:
 
* [http://tecfa.unige.ch/guides/xml/examples/xpath/xpath-jungle-2.xml xpath-jungle-2.xml]
          &lt;li&gt;Bernadette&lt;/li&gt;
 
          &lt;li&gt;Nathalie&lt;/li&gt;
 
      &lt;/ul&gt;


 
=== Location wildcards ===
 
=== 2.5 Location wildcards ===


* Sometimes (but not often!), it is useful to work with wildcards
* Sometimes (but not often!), it is useful to work with wildcards
* You have to understand that only '' one'' rule will be applied/element. Rules with wildcards have less priority and this is why "your rules" are applied before the system defaults.
* You have to understand that only ''one'' rule will be applied per element. Rules with wildcards have less priority and btw. this is why "your rules" are applied before the system default rules.
 
 
 
==== Find all child nodes of type XML element ====
 
'' *''
 
 
 
==== Find all child nodes (including comments, etc.) ====
 
'' node()''
 
 
 
==== Find all element attributes ====


'' @*''
; Find all child nodes of type XML element
: ''*''


; Find all child nodes (including comments, etc.)
: ''node()''


; Find all element attributes
: ''@*''


==== Find all text nodes ====
; Find all text nodes
: ''text()''


text()
; Combine locations
: use the "|" operator, an example is just below.


Example: XSLT includes two '''built-in default rules'''. They rely on using these wildcards.


This rule applies to the document root and all other elements
<source lang="xml">
<xsl:template match="*|/">
  <xsl:apply-templates/>
</xsl:template>
</source>


===== FYI: The system built-in (default) rules rely on wildcards =====
Text and attribute values are just copied
<source lang="xml">
<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>
</source>


This rule applies to the document root and all other elements (see [xml-xpath.html#23299 2.8 ���%G�₁��%@���Union of XPaths���%G�₁��%@ [25]])
== XPaths with predicates ==


&lt;xsl:template match="*|/"&gt;
Let us now scale up a bit.


  &lt;xsl:apply-templates/&gt;
* A predicate is an ''expression that can be true or false''
 
* It is appended within [...] to a given location path and will ''refine results''
&lt;/xsl:template&gt;
 
Text and attribute values are just copied (see
 
&lt;xsl:template match="text()|@*"&gt;
 
  &lt;xsl:value-of select="."/&gt;
 
&lt;/xsl:template&gt;
 
 
 
=== 2.6 XPaths with predicates ===
 
* A predicate is an '' expression that can be true or false''
* It is appended within [...] to a given location path and will '' refine results''
* More than one predicate can be appended to and within (!) a location path
* More than one predicate can be appended to and within (!) a location path
* Expressions can contain mathematical or boolean operators
* Expressions can contain mathematical or boolean operators


 
; Find element number N in a list
 
: Syntax: ''XML_element_name [ N ]''
==== Find element number N in a list ====
 
'' XML_element_name '' '' [ N ]''
 
/project/participants/participant''[2]''


  /project/participants/participant''[2]''
  /project/participants/participant''[2]''
  /FirstName
  /project/participants/participant''[2]''/FirstName
 
 
 
==== Find elements that have a given attribute ====
 
'' XML_element_name [ @attribute_name ]''
 
 
 
==== Find elements that have a given element as child ====
 
'' XML_element_name [ XML_element_name ]''
 
//participant[FoodPref]
 


; Find elements that have a given attribute
: Synatx: ''XML_element_name [ @attribute_name ]''
//difficulty[@level]


===== Mathematical expressions =====
; Find elements that have a given element as child
: Syntax '' XML_element_name [ XML_element_name ]''//participant[FoodPref]
: Note: this is not the same as //participant/FoodPref. The latter would return a list of ''FoodPref'' elements, whereas the former returns a list of ''participant''


* Use the standard operators, except '' div'' instead of'' /'' ")
; Mathematical expressions


- * div mod
* Use the standard operators, except '' div'' instead of ''/'' (for obvious reasons)
- * div mod


* mod is interesting if you want to display a long list in table format
* mod is interesting if you want to display a long list in table format
5 mod 2 returns 1, as will "7 mod 2" and "3 mod 2"


5 mod 2 returns 1, "7 mod 2" and "3 mod 2" too
; Boolean operators (comparison, and, or)
 
 
 
===== Boolean operators (comparison, and, or) =====


* List of operators (according to precedence)
* List of operators (according to precedence)
: &lt;=, &lt;, &gt;=, &gt;
: =, !=
: and, or


&lt;=, &lt;, &gt;=, &gt;


<nowiki>=, !=</nowiki>
; Examples
 
and
 
or
 
 
 
===== Examples =====


* Return all exercise titles with a grade bigger than 5.
* Return all exercise titles with a grade bigger than 5.
 
: //exercise[note&gt;5]/title
//exercise[note&gt;5]/title


* Find elements that have a given attribute with a given value
* Find elements that have a given attribute with a given value
 
: Recall of the Syntax:  ''XML_element_name [ @attribute_name="value"]''
'' XML_element_name [ @attribute_name = ���%G�₁��%@���value���%G�₁��%@���]''
: //solutions/item[@val="low"]
 
//solutions/item''[@val="low"]''
 
'' ''


* Example XSLT template that will match all item elements with val="low".
* Example XSLT template that will match all item elements with val="low".


&lt;xsl:template match="'' //item[@val=���%G�₁��%@���low���%G�₁��%@���]'' "&gt;
<source lang="xml">
 
<xsl:template match="'//item[@val='low']">
&lt;xsl:value-of select="." /&gt;
    <xsl:value-of select="." />
 
</xsl:template>
&lt;/xsl:template&gt;
</source>


Usually expressions also contain functions as we shall see below, examples:


 
* Return the last five elements of a list
===== Note: Usually expression also contain functions (see [xml-xpath.html#21068 2.7 ���%G�₁��%@���XPath functions���%G�₁��%@ [21]]) =====
 
* Return last five elements of a list
 
  author [(last() - 4) &lt;= position()) and (position() &lt;= last())]
  author [(last() - 4) &lt;= position()) and (position() &lt;= last())]


* Return all '' Participant'' nodes with a contents of '' FirstName'' bigger than 7 characters:
* Return all ''Participant'' nodes with a contents of ''FirstName'' bigger than 7 characters:
 
  "//Participant[string-length(FirstName)&gt;=8]"
  "//Participant[string-length(FirstName)&gt;=8]"


==== Example: Retrieve selected elements ====


The following example will retrieve the following:
* All persons who do have a food preference
* All items that have an a "priority" attribute set to "high"


==== Example 2-3: Retrieve selected elements ====
;The XSLT stylesheet (file [http://tecfa.unige.ch/guides/xml/examples/xpath/xpath-jungle-3.xsl xpath-jungle-3.xsl])
 
 
 
===== The XSLT stylesheet (file xpath-jungle-3.xsl) =====
 
&lt;xsl:template match="/"&gt;
 
  &lt;html&gt;
 
    &lt;body bgcolor="#FFFFFF"&gt;
 
      &lt;h1&gt;Retrieve selected elements&lt;/h1&gt;
 
      ''Here is the name of participant two: ''
 
        &lt;ul&gt;&lt;li&gt;&lt;xsl:value-of select="''.//participant[2]/FirstName''
"/&gt;&lt;/li&gt;&lt;/ul&gt;
 
      ''Here are all participant's firstnames that have a food preference:''
 
      &lt;ul&gt;&lt;xsl:apply-templates select="''.//participant[FoodPref]''
"/&gt;&lt;/ul&gt;
 
      ''Here are all items that have a value of "high"''
 
      &lt;ul&gt;&lt;xsl:apply-templates select="''.//item[@val='high']''
"/&gt;&lt;/ul&gt;
 
    &lt;/body&gt;
 
  &lt;/html&gt;
 
&lt;/xsl:template&gt;
 
��
 
&lt;xsl:template match="participant"&gt;
 
  &lt;li&gt;&lt;xsl:value-of select="FirstName"/&gt;&lt;/li&gt;
 
&lt;/xsl:template&gt;
 
��
 
&lt;xsl:template match="item"&gt;
 
  &lt;li&gt;&lt;xsl:value-of select="."/&gt;&lt;/li&gt;
 
&lt;/xsl:template&gt;
 
��
 
 
 
===== HTML result =====
 
&lt;html&gt;
 
    &lt;body bgcolor="#FFFFFF"&gt;
 
      &lt;h1&gt;Retrieve selected elements&lt;/h1&gt;
 
      Here is the name of participant two:
 
      &lt;ul&gt;
 
          &lt;li&gt;Jonathan&lt;/li&gt;
 
      &lt;/ul&gt;
 
      Here are all participant's firstnames that have a food preference:
 
 
      &lt;ul&gt;
 
          &lt;li&gt;Daniel&lt;/li&gt;
 
          &lt;li&gt;Jonathan&lt;/li&gt;
 
      &lt;/ul&gt;
 
      Here are all items that have a value of "high"
 
      &lt;ul&gt;
 
          &lt;li&gt;Register for a XSLT course and do exercices&lt;/li&gt;
 
          &lt;li&gt;Register for a XPath course and do exercices&lt;/li&gt;
 
      &lt;/ul&gt;
 
    &lt;/body&gt;
 
&lt;/html&gt;
 
 
 
=== 2.7 XPath functions ===
 
* XPath defines a certain number of functions
** You can recognize a function because it has "()".
* Functions are programming constructs that will return various kinds of informations, e.g.
** true / false
** a number
** a string
** a list of nodes
* It is not obvious to understand these ....
* There are restrictions on how you can use functions (stick to examples or the reference)
 
 
 
==== last() ====
 
last() gives the number or nodes within a context
 
 
 
==== position() ====
 
position() returns the position of an element with respect to other children for a parent
 
 
 
==== count(node-set) ====
 
count gives the number of nodes in a node set (usually found with an XPath).
 
 
 
==== starts-with(string, string) ====
 
returns TRUE if the second string is part of the first and starts off the first
 
//Participant[starts-with(Firstname,���%G�₁��%@���Berna���%G�₁��%@���)]"
 
 
 
==== contains(string, string) ====
 
returns TRUE if the second string is part of the first
 
//Participant[contains(FirstName,���%G�₁��%@���nat���%G�₁��%@���)]


<source lang="XML">
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">


  <xsl:output method="html"/>


==== string-length(string) ====
  <xsl:template match="/">
    <html>
      <body bgcolor="#FFFFFF">
        <h1>Retrieve selected elements</h1>
        Here is the name of participant two:
        <ul><li><xsl:value-of select=".//participant[2]/FirstName"/></li></ul>
        Here are all participant's firstnames that have a food preference:
        <ul><xsl:apply-templates select=".//participant[FoodPref]"/></ul>
        Here are all items that have a value of "high"
        <ul><xsl:apply-templates select=".//item[@val='high']"/></ul>
      </body>
    </html>
  </xsl:template>


returns the length of a string
<xsl:template match="participant">
  <li><xsl:value-of select="FirstName"/></li>
</xsl:template>


<xsl:template match="item">
  <li><xsl:value-of select="."/></li>
</xsl:template>


</xsl:stylesheet>
</source>


==== number(string) ====
;HTML result


transforms a string into a number
<source lang="xml">
<html>
  <body bgcolor="#FFFFFF">
      <h1>Retrieve selected elements</h1>
      Here is the name of participant two:
      <ul>
        <li>Jonathan</li>
      </ul>
      Here are all participant's firstnames that have a food preference:
      <ul>
        <li>Daniel</li>
        <li>Jonathan</li>
      </ul>
      Here are all items that have a value of "high"
      <ul>
        <li>Register for a XSLT course and do exercices</li>
        <li>Register for a XPath course and do exercices</li>
      </ul>
  </body>
</html>
</source>


Live example:
* [http://tecfa.unige.ch/guides/xml/examples/xpath/xpath-jungle-3.xml xpath-jungle-3.xml]
* [http://tecfa.unige.ch/guides/xml/examples/xpath/xpath-jungle-3.xsl xpath-jungle-3.xsl]


Below is a more complex example. One in short notation and the other (to do) in it equivalent long notations:


==== sum(node-set) ====
<syntaxhighlight lang="XML">
/outputTree/command/pivotTable/dimension//category[@text='Measurement']/dimension/category/cell[@text='Nominal']
</syntaxhighlight>


computes the sum of a given set of nodes. <br /> If necessary, does string conversion with number()


== XPath functions ==


XPath defines a certain number of functions. You can recognize a function because it has appended "()".


==== round(number) ====
Functions are programming constructs that will return various kinds of informations, e.g.
* true / false
* a number
* a string
* a list of nodes


round a number, e.g. 1.4 becomes 1 and 1.7 becomes 2
It is not obvious to understand what all of these functions do. For example, there are restrictions on how you can use functions (stick to examples or the reference)


; last()
: last() gives the number or nodes within a context


; position()
: position() returns the position of an element with respect to other children in the same parent
: Warning: The result will include empty nodes create from whitespaces between elements. To avoid this you should strip the parent nodes using
<source lang="xml">
<xsl:strip-space elements="name_of_the_parent_node"/>
</source>


==== translate(string1, string2, string3) ====
; count(node-set)
: count gives the number of nodes in a node set
We got <xsl:value-of select="count(//problem)"/> problems,  
: i.e. it will count N elements retrieved and not the child elements of ''problem''
: Live example: [http://tecfa.unige.ch/guides/xml/examples/xpath/xpath-jungle-6.xml xpath-jungle-6.xml] - [http://tecfa.unige.ch/guides/xml/examples/xpath/xpath-jungle-6.xsl xpath-jungle-6.xsl]


translates string1 by substituting string2 elements with string3 elements
; starts-with(string, string)
: returns TRUE if the second string is part of the first and starts off the first
//Participant[starts-with(Firstname,'Berna')]"


(See next slides for examples ....)
; contains(string, string)
: returns TRUE if the second string is part of the first
//Participant[contains(FirstName,'nat')]


; string-length(string)
: returns the length of a string


; number(string)
: transforms a string into a number


==== Example 2-4: Computation of an average ====
; sum(node-set)
: computes the sum of a given set of nodes. <br /> If necessary, does string conversion with number()


* We would like to compute the average of participant���%G�₁��%@���s qualifications
; round(number)
: round a number, e.g. 1.4 becomes 1 and 1.7 becomes 2


&lt;participant&gt;&lt;FirstName&gt;Daniel&lt;/FirstName&gt;
; translate(string1, string2, string3)
: translates string1 by substituting string2 elements with string3 elements


              ''&lt;qualification&gt;8&lt;/qualification&gt;''
=== Example: Computation of an average ===
    &lt;/participant&gt;


* We would like to compute the average of participant's qualifications
<source lang="xml">
<participant><FirstName>Daniel</FirstName>
              ''<qualification>8</qualification>''
    </participant>
</source>


 
;The XSLT stylesheet (file [http://tecfa.unige.ch/guides/xml/examples/xpath/xpath-jungle-4.xsl xpath-jungle-4.xsl]
===== The XSLT stylesheet (file xpath-jungle-4.xsl) =====


* We compute the sum of a node-set and then divide by the number of nodes
* We compute the sum of a node-set and then divide by the number of nodes


&lt;xsl:template match="/"&gt;
<source lang="XML">
 
<?xml version="1.0" encoding="utf-8"?>
    &lt;html&gt;
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 
                version="1.0">
      &lt;body bgcolor="#FFFFFF"&gt;
 
        &lt;h1&gt;Qualification level of participants&lt;/h1&gt;
 
        Average is
 
        '' &lt;xsl:value-of select=''
''"sum(.//participant/qualification) div ''
 
''                              count(.//participant/qualification)"''
''/&gt;''
 
      &lt;/body&gt;
 
    &lt;/html&gt;
 
  &lt;/xsl:template&gt;
 
 
 
===== HTML result =====


&lt;html&gt;
  <xsl:output method="html"/>


     &lt;body bgcolor="#FFFFFF"&gt;
  <xsl:template match="/">
 
     <html>
      &lt;h1&gt;Qualification level of participants&lt;/h1&gt;
      <body bgcolor="#FFFFFF">
        <h1>Qualification level of participants</h1>
        Average is
        <xsl:value-of select="sum(.//participant/qualification) div count(.//participant/qualification)"/>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>
</source>


;HTML result
<source lang="xml">
<html>
    <body bgcolor="#FFFFFF">
      <h1>Qualification level of participants</h1>
       Average is
       Average is
       5.75
       5.75
    </body>
</html>
</source>


    &lt;/body&gt;
Live example:
* [http://tecfa.unige.ch/guides/xml/examples/xpath/xpath-jungle-4.xml xpath-jungle-4.xml]


&lt;/html&gt;
=== Example: Find first names containing 'nat' ===


;The XSLT stylesheet (file [http://tecfa.unige.ch/guides/xml/examples/xpath/xpath-jungle-5.xsl xpath-jungle-5.xsl]


<source lang="XML">
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">


==== Example 2-5: Find first names containing ���%G�₁��%@���nat���%G�₁��%@��� ====
  <xsl:output method="html"/>


  <xsl:template match="/">
    <html>
      <body bgcolor="#FFFFFF">
        <h1>Do we have a "nat" ?</h1>
        First Names that contain "nat":
        <ul><xsl:apply-templates select=".//participant[contains(FirstName,'nat')]"/></ul>
        First Names that contain "nat" and "Nat":
        <ul><xsl:apply-templates select=".//participant[contains(translate(FirstName,'N','n'),'nat')]"/></ul>
      </body>
    </html>
  </xsl:template>


<xsl:template match="participant">
  <li><xsl:value-of select="FirstName"/></li>
</xsl:template>


===== The XSLT stylesheet (file xpath-jungle-5.xsl) =====
</xsl:stylesheet>
</source>


&lt;xsl:template match="/"&gt;
Live example
* [http://tecfa.unige.ch/guides/xml/examples/xpath/xpath-jungle-5.xml xpath-jungle-5.xml]


  &lt;html&gt;
== Union of XPaths ==


  &lt;body bgcolor="#FFFFFF"&gt;
Union Xpaths combine more than one XPath (and all the resulting nodes are returned). A typical example that we already introduced above is the default rule which means that the template matches either the root element (i.e. "/" or just any element),
<source lang="xml">
<xsl:template match="*|/">
  <xsl:apply-templates/>
</xsl:template>
</source>


  &lt;h1&gt;Do we have a "nat" ?&lt;/h1&gt;
Often, this construct is used to simplify apply-templates or even templates themselves. E.g. the following rules applies to both "description" and "para" elements.


  ''First Names that contain "nat":''
<source lang="xml">
<xsl:template match="para|description">
  <p><xsl:apply-templates/></p>
</xsl:template>
</source>


  &lt;ul&gt;
== List of commonly used XPath expressions ==
 
  &lt;xsl:apply-templates select="''.//participant[contains(FirstName,'nat')''
]"/&gt;
 
  &lt;/ul&gt;
 
  ''First Names that contain "nat" and "Nat":''
 
  &lt;ul&gt;
 
    &lt;xsl:apply-templates select="''.//participant[contains''
 
''                        (translate(FirstName,'N','n'),'nat')]''
"/&gt;
 
    &lt;/ul&gt;
 
  &lt;/body&gt;
 
  &lt;/html&gt;
 
&lt;/xsl:template&gt;
 
��
 
&lt;xsl:template match="participant"&gt;
 
  &lt;li&gt;&lt;xsl:value-of select="FirstName"/&gt;&lt;/li&gt;
 
&lt;/xsl:template&gt;
 
 
 
=== 2.8 Union of XPaths ===
 
* Union Xpaths combine more than one XPath (and all the resulting nodes are returned).
* A typical example is the default rule which means that the template matches either the root element (i.e. "/" or just any element),
 
&lt;xsl:template match="*|/"&gt;
 
  &lt;xsl:apply-templates/&gt;
 
&lt;/xsl:template&gt;
 
* Often this is used to simplify apply-templates or even templates themselves. E.g. the following rules applies to both "description" and "para" elements.
 
&lt;xsl:template match="para|description"&gt;
 
  &lt;p&gt;&lt;xsl:apply-templates/&gt;&lt;/p&gt;
 
&lt;/xsl:template&gt;
 
 
 
=== 2.9 List of commonly used XPath expressions ===


{| border="1"
{| border="1"
Line 1,019: Line 836:
|-
|-
| rowspan="1" colspan="1" |
| rowspan="1" colspan="1" |
@attr=���%G�₁��%@���value���%G�₁��%@���
@attr='value'
| rowspan="1" colspan="1" |
| rowspan="1" colspan="1" |
value of attribute
value of attribute
| rowspan="1" colspan="1" |
| rowspan="1" colspan="1" |
list[@type=���%G�₁��%@���ol���%G�₁��%@���]
list[@type='ol']
| rowspan="1" colspan="1" |
| rowspan="1" colspan="1" |
'' &lt;list type="ol"&gt; ...... &lt;/list&gt;''
'' &lt;list type="ol"&gt; ...... &lt;/list&gt;''
Line 1,049: Line 866:




Important:
* The XML standard requires that an XML parser returns emtpy space between elements as empty nodes. In other words, functions such as ''location()'' or ''last()'' will also count empty nodes ! Tell XSLT to remove these within the elements within which you need to count.


== 3. XSLT reminder ==
Good code:
 
: <xsl:strip-space elements="name_of_the_parent"/>
* In most situations, writing simple XSLT rules will do
* Do not attempt to use looping constructs etc. when you don���%G�₁��%@���t have to
* There is no special "magic" for dealing with images, links, stylesheets etc. Simply:
** look at your XML
** figure out how to translate into equivalent HTML (or whatever you are translating into)
 
 
 
==== Example 3-1: Dealing with pictures ====
 
 
 
===== XML file with picture file names (file images.xml) =====
 
&lt;?xml version="1.0"?&gt;
 
&lt;?xml-stylesheet href="images.xsl" type="text/xsl"?&gt;
 
&lt;page&gt;
 
  &lt;title&gt;Hello Here are my images&lt;/title&gt;
 
  &lt;list&gt;
 
    ''&lt;image&gt;''
dolores_001.jpg''&lt;/image&gt;''
 
    &lt;image&gt;dolores_002.jpg&lt;/image&gt;
 
    &lt;image&gt;dolores_002.jpg&lt;/image&gt;
 
    &lt;image2&gt;scrolls.jpg &lt;/image2&gt;
 
    &lt;image2&gt;scrolls.jpg &lt;/image2&gt;
 
    ''&lt;image3''
  source="dolores_002.jpg"&gt;Recipe image''&lt;/image3&gt;''
 
  &lt;/list&gt;
 
  &lt;comment&gt;Written by DKS.&lt;/comment&gt;
 
&lt;/page&gt;
 
��
 
 
 
===== XSLT stylesheet (file images.xsl) =====
 
&lt;xsl:template match="list"&gt;
 
    Apply templates for image elements:
 
    &lt;xsl:apply-templates select="''image''
"/&gt;
 
    This will only insert the first "image2" element contents it finds:
 
    &lt;p&gt; &lt;img src="{image2}"/&gt; &lt;/p&gt;
 
    And another template for a tag image3 element (with an attribute)
 
    &lt;xsl:apply-templates select="''image3''
"/&gt;
 
&lt;/xsl:template&gt;
 
* This rule will insert the content of the image element into the value of src="".
 
  &lt;xsl:template match="image"&gt;
 
    &lt;p&gt; &lt;img src="''{.}''
"/&gt; &lt;/p&gt;
 
  &lt;/xsl:template&gt;
 
* This rule will insert the value of the source attribute into the value of src and also insert the contents of the the image3 element.
 
  &lt;xsl:template match="image3"&gt;
 
    &lt;p&gt; &lt;img src="''{@source}''
"/&gt;''&lt;xsl:value-of select="."/&gt;''
  &lt;/p&gt;
 
  &lt;/xsl:template&gt;
 
 
 
== 4. Multiple templates for one element ==
 
* XSLT allows to define multiple rules for the same XPath by using the "mode" attribute
* This construct is frequently used to produce table of contents
 
 
 
===== Parts of the XML file (file douglas-recipes.xml) =====
 
&lt;list&gt;
 
  &lt;recipe id="r1"&gt;
 
    &lt;recipe_name&gt;TACOS&lt;/recipe_name&gt;
 
    &lt;meal&gt;Dinner&lt;/meal&gt;
 
    &lt;ingredients&gt;
 
      &lt;item&gt;3 taco shells&lt;/item&gt;
 
      &lt;item&gt;1 pkg hamburger 100g&lt;/item&gt;
 
      ........
 
    &lt;/ingredients&gt;
 
��
 
    &lt;directions&gt;
 
      &lt;bullet&gt;Oven on at 180 degrees.&lt;/bullet&gt;
 
      ......
 
      &lt;bullet&gt;Cut up lettuce.&lt;/bullet&gt;
 
    &lt;/directions&gt;
 
  &lt;/recipe&gt;
 
��
 
  &lt;recipe id="r2"&gt;
 
  ....
 
&lt;/list&gt;
 
 
 
===== XSLT fragment (file douglas-recipes.xsl) =====
 
&lt;xsl:template match="list"&gt;
 
  &lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
 
    &lt;head&gt; &lt;title&gt;Recipes&lt;/title&gt; &lt;/head&gt;
 
    &lt;body bgcolor="#ffffff"&gt;
 
    &lt;h1&gt;Recipes&lt;/h1&gt;
 
    &lt;h2&gt;Contents&lt;/h2&gt;
 
    &lt;p&gt; &lt;xsl:apply-templates ''select="recipe" mode="toc"/''
&gt; &lt;/p&gt;
 
    &lt;xsl:apply-templates select="''recipe''
"/&gt;
 
    &lt;/body&gt; &lt;/html&gt;
 
&lt;/xsl:template&gt;
 
* We define 2 rules for "recipe": One will have a mode="toc"
* The next rule will create the table of contents.
** It will use the recipe_name as link
** It will use the id attribute to create an internal href link
 
&lt;xsl:template ''match="recipe" mode="toc"''
&gt;
 
  &lt;p&gt;&lt;a ''href="#{@id}''
"&gt;&lt;xsl:value-of select="''recipe_name''
"/&gt;&lt;/a&gt;&lt;/p&gt;
 
&lt;/xsl:template&gt;
 
* This rule is almost "normal", except that we insert a name anchor
 
&lt;xsl:template ''match="recipe"''
&gt;
 
  &lt;h1&gt;&lt;a ''name="{@id}''
"&gt;&lt;xsl:value-of select="recipe_name"/&gt;&lt;/a&gt; &lt;/h1&gt;
 
  &lt;xsl:apply-templates select="meal"/&gt;
 
  &lt;xsl:apply-templates select="ingredients"/&gt;
 
  &lt;xsl:apply-templates select="directions"/&gt; &lt;/xsl:template&gt;
 
 
 
===== HTML result =====
 
&lt;?xml version="1.0" encoding="iso-8859-1"?&gt;
 
��
 
&lt;!DOCTYPE html
 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
 
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
 
    &lt;head&gt;
 
      &lt;title&gt;Recipes&lt;/title&gt;
 
    &lt;/head&gt;
 
    &lt;body bgcolor="#ffffff"&gt;
 
      &lt;h1&gt;Recipes&lt;/h1&gt;
 
      &lt;h2&gt;Contents&lt;/h2&gt;
 
      &lt;p&gt;
 
          &lt;p&gt; ''&lt;a href="#r1"&gt;TACOS&lt;/a&gt; ''
&lt;/p&gt;
 
          &lt;p&gt; ''&lt;a href="#r2"&gt;VOL AU VENT (one person)&lt;/a&gt; ''
&lt;/p&gt;
 
      &lt;/p&gt;
 
      &lt;hr/&gt;
 
      &lt;h1&gt;
 
        '' &lt;a name="r1"&gt;TACOS&lt;/a&gt;''
 
      &lt;/h1&gt;
 
      &lt;p&gt; Type: Dinner&lt;/p&gt;
 
 
 
== 5. Conditional XSLT and whitespaces ==
 
* Although many conditionals can be expressed with XPath and according selection rules, XSLT provides 2 typical programming constructs to handle "if" and "if-then-else" situations.
* When you use XPath functions like position(), you have to be very careful about whitespaces
 
 
 
=== 5.1 Simple if ===
 
 
 
==== Syntax for xsl:if: ====
 
&lt;xsl:if test = "boolean_expression"&gt;
 
&lt;!-- Content or xsl instructions here --&gt;
 
&lt;/xsl:if&gt;
 
 
 
==== Example 5-1: Display lists, the last element differently with xsl:if ====
 
* Warning: This only works in standards compliant browsers if you either eliminate whitespaces from your XML file or if you add the following XSL instruction at the beginning:
 
&lt;xsl:strip-space elements="element_name element_name ...."/&gt;
 
&lt;xsl:strip-space elements="ingredients"/&gt;
 
 
 
===== XML (file ingredient-list.xml) =====
 
&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;
 
&lt;?xml-stylesheet href="ingredient-list.xsl" type="text/xsl"?&gt;
 
&lt;ingredients&gt;
 
  &lt;item&gt;3 taco shells&lt;/item&gt;
 
  &lt;item&gt;1 pkg hamburger 100g&lt;/item&gt;
 
  &lt;item&gt;Taco mix&lt;/item&gt;&lt;item&gt;Lettuce&lt;/item&gt;&lt;/ingredients&gt;
 
 
 
===== XSL (file ingredient-list.xsl) =====
 
  &lt;xsl:template match="/ingredients"&gt;
 
  &lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
 
    &lt;head&gt; &lt;title&gt;Ingrediant list&lt;/title&gt; &lt;/head&gt;
 
    &lt;body bgcolor="#ffffff"&gt;
 
      Here is a list of recipe ingrediants:
 
    &lt;p&gt; &lt;xsl:apply-templates select="item"/&gt;. &lt;/p&gt;
 
      Here is a list of recipe ingrediants, this time numbered:
 
    &lt;p&gt; &lt;xsl:apply-templates select="item" mode="numb"/&gt;. &lt;/p&gt;
 
    &lt;/body&gt;
 
  &lt;/html&gt;
 
&lt;/xsl:template&gt;
 
��
 
&lt;xsl:template match="item"&gt;
 
  &lt;xsl:value-of select="."/&gt;
 
  &lt;xsl:if ''test="position()!=last()"''
&gt; &lt;xsl:text&gt;, &lt;/xsl:text&gt; &lt;/xsl:if&gt;
 
&lt;/xsl:template&gt;
 
��
 
&lt;xsl:template match="item" mode="numb"&gt;
 
  (&lt;xsl:value-of select="''position()''
"/&gt;)
 
  &lt;xsl:value-of select="."/&gt;
 
  &lt;xsl:if ''test="position()!=last()"''
&gt; &lt;xsl:text&gt;, &lt;/xsl:text&gt; &lt;/xsl:if&gt;
 
&lt;/xsl:template&gt;
 
��
 
&lt;/xsl:stylesheet&gt;
 
 
 
===== HTML results =====
 
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
 
    &lt;head&gt;
 
      &lt;title&gt;Ingrediant list&lt;/title&gt;
 
    &lt;/head&gt;
 
    &lt;body bgcolor="#ffffff"&gt;
 
      Here is a list of recipe ingrediants:
 
    &lt;p&gt;3 taco shells'',''
  1 pkg hamburger 100g'',''
  Taco mix'',''
  Lettuce''.''
  &lt;/p&gt;
 
      Here is a list of recipe ingrediants, this time numbered:
 
    &lt;p&gt;
 
  ''(1)''
  3 taco shells'',''
 
  ''(2) ''
1 pkg hamburger 100g,
 
  (3) Taco mix,
 
  (4) Lettuce. &lt;/p&gt;
 
    &lt;/body&gt;
 
&lt;/html&gt;
 
 
 
===== Same logic would apply e.g. to building references =====
 
&lt;xsl:template match="reference"&gt;
 
  &lt;xsl:apply-templates
 
        select="author|ref|title|edition|publisher|pubPlace|publicationYear"/&gt;.
 
  &lt;/xsl:template&gt;
 
  ��
 
  &lt;xsl:template match="author|edition|publisher|pubPlace|publicationYear"&gt;
 
  &lt;xsl:apply-templates/&gt;
 
  &lt;xsl:if test="position() !=last()"&gt;, &lt;/xsl:if&gt;
 
  &lt;/xsl:template&gt;
 
 
 
=== 5.2 If-then-else ===
 
 
 
==== Syntax: ====
 
&lt;xsl:choose&gt;
 
&lt;!-- Content: (xsl:when , xsl:otherwise?) --&gt;
 
&lt;/xsl:choose&gt;
 
&lt;xsl:when test = "boolean-expression"&gt;
 
&lt;!-- Content: template --&gt;
 
&lt;/xsl:when&gt;
 
&lt;xsl:otherwise&gt;
 
&lt;!-- Content: template --&gt;
 
&lt;/xsl:otherwise&gt;
 
 
 
==== Example 5-2: Animal colors with xsl:choose ====
 
 
 
===== XML (file animals.xml) =====
 
&lt;example&gt;
 
  &lt;title&gt;Animals with colors&lt;/title&gt;
 
  &lt;list&gt;
 
  &lt;animal color="black"&gt;Panther&lt;/animal&gt;
 
  &lt;animal color="complicated with spots"&gt;Panther&lt;/animal&gt;
 
  &lt;animal color="white"&gt;Polar bear&lt;/animal&gt;
 
  &lt;animal color="green"&gt;Frog&lt;/animal&gt;
 
  &lt;animal&gt;Cow&lt;/animal&gt;
 
  &lt;/list&gt;
 
&lt;/example&gt;
 
 
 
===== XSLT template for animal (file animals:xsl) =====
 
&lt;xsl:template match="animal"&gt;
 
&lt;li&gt;
 
  &lt;xsl:choose&gt;
 
    &lt;xsl:when ''test="@color='black'"''
&gt;
 
      &lt;p style="color:black;font-weight:bold;"&gt; &lt;xsl:value-of select="."/&gt; &lt;/p&gt;
 
    &lt;/xsl:when&gt;
 
��
 
    &lt;xsl:when ''test="@color='green'"''
&gt;
 
      &lt;p style="color:green;font-weight:bold;"&gt; &lt;xsl:value-of select="."/&gt; &lt;/p&gt;
 
    &lt;/xsl:when&gt;
 
��
 
    &lt;xsl:''otherwise''
&gt;
 
      &lt;p style="color:cyan"&gt; &lt;xsl:value-of select="."/&gt; &lt;/p&gt;
 
    &lt;/xsl:otherwise&gt;
 
  &lt;/xsl:choose&gt;
 
&lt;/li&gt;
 
&lt;/xsl:template&gt;
 
 
 
===== HTML (some) =====
 
&lt;li&gt;&lt;p style="color:black;font-weight:bold;"&gt;Panther&lt;/p&gt; &lt;/li&gt;
 
&lt;li&gt;&lt;p style="color:cyan"&gt;Panther&lt;/p&gt;&lt;/li&gt;
 
&lt;li&gt;&lt;p style="color:cyan"&gt;Polar bear&lt;/p&gt;&lt;/li&gt;
 
&lt;li&gt;&lt;p style="color:green;font-weight:bold;"&gt;Frog&lt;/p&gt;&lt;/li&gt;
 
&lt;li&gt;&lt;p style="color:cyan"&gt;Cow&lt;/p&gt;&lt;/li&gt;
 
 
 
== 6. Looping ==
 
* Most of the time you do "looping" with templates (as in all previous examples)
* There is a xsl:for-each looping construct. It is useful to write more compact code, to use it with sorting and functional programming constructs (not explained here).
 
'' xsl:for-each select="XPath" ''
 
 
 
==== Example 6-1: Translating database query output into an HTML table ====
 
 
 
===== XML (file rowset.xml) =====
 
* Typical database query output may look like this
* E.g. survey data will present as a series of rows of the same length
* We would like to translate each ROW into a table row and each child as a table cell
 
��
 
&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;
 
&lt;?xml-stylesheet href="rowset.xsl" type="text/xsl"?&gt;
 
&lt;page&gt;
 
  &lt;ROWSET&gt;
 
    &lt;ROW&gt;&lt;id&gt;1&lt;/id&gt;&lt;login&gt;test&lt;/login&gt;&lt;fullname&gt;Joe Test &lt;/fullname&gt;
 
    &lt;food&gt;3&lt;/food&gt;&lt;work&gt;4&lt;/work&gt;&lt;love&gt;5&lt;/love&gt;&lt;leisure&gt;2&lt;/leisure&gt;&lt;/ROW&gt;
 
    &lt;ROW&gt;&lt;id&gt;2&lt;/id&gt;&lt;login&gt;test2&lt;/login&gt;&lt;fullname&gt;Janine Test &lt;/fullname&gt;
 
    &lt;food&gt;3&lt;/food&gt;&lt;work&gt;4&lt;/work&gt;&lt;love&gt;6&lt;/love&gt;&lt;leisure&gt;2&lt;/leisure&gt;&lt;/ROW&gt;
 
  .......
 
  &lt;/ROWSET&gt;
 
&lt;/page&gt;
 
 
 
===== XSLT (file rowset.xsl) =====
 
&lt;xsl:template match="ROWSET"&gt;
 
    &lt;table border="2" cellspacing="1" cellpadding="6"&gt;
 
    &lt;tr&gt;&lt;th&gt;id&lt;/th&gt;
 
        &lt;th&gt;Login&lt;/th&gt;
 
        &lt;th&gt;Full Name&lt;/th&gt;
 
        &lt;th&gt;food&lt;/th&gt;&lt;th&gt;work&lt;/th&gt;&lt;th&gt;love&lt;/th&gt;&lt;th&gt;leisure&lt;/th&gt;
 
      &lt;/tr&gt;
 
      ''&lt;xsl:for-each select="ROW"&gt;''
 
      &lt;tr&gt;
 
      &lt;td&gt;&lt;xsl:value-of select="id"/&gt;&lt;/td&gt;
 
      &lt;td&gt;&lt;xsl:value-of select="login"/&gt;&lt;/td&gt;
 
      &lt;td&gt;&lt;xsl:value-of select="fullname"/&gt;&lt;/td&gt;
 
      &lt;td&gt;&lt;xsl:value-of select="food"/&gt;&lt;/td&gt;
 
      &lt;td&gt;&lt;xsl:value-of select="work"/&gt;&lt;/td&gt;
 
      &lt;td&gt;&lt;xsl:value-of select="love"/&gt;&lt;/td&gt;
 
      &lt;td&gt;&lt;xsl:value-of select="leisure"/&gt;&lt;/td&gt;
 
      &lt;/tr&gt;
 
      ''&lt;/xsl:for-each&gt;''
 
    &lt;/table&gt;
 
&lt;/xsl:template&gt;
 
 
 
=== 6.1 Looping with a sort ===
 
* xsl:sort can sort a list according to several criteria, can be used more than once
 
&lt;xsl:sort
 
  ''select = "Xpath"''
 
  data-type = { "text" | "number" }
 
  order = { "ascending" | "descending" }
 
  case-order = { "upper-first" | "lower-first" } /&gt;
 
 
 
==== Example 6-2: Sort a participants list according to qualification ====
 
 
 
===== XML fragment (file: participants.xml) =====
 
&lt;?xml version="1.0"?&gt;
 
&lt;?xml-stylesheet href="participants.xsl" type="text/xsl"?&gt;
 
  &lt;participants&gt;
 
  &lt;participant&gt;
 
    &lt;FirstName&gt;Daniel&lt;/FirstName&gt;
 
    &lt;qualification&gt;8&lt;/qualification&gt;
 
    &lt;description&gt;Daniel will be the tutor&lt;/description&gt;
 
    &lt;FoodPref picture="dolores_001.jpg"&gt;Sea Food&lt;/FoodPref&gt;
 
  &lt;/participant&gt;
 
  &lt;participant&gt;
 
    &lt;FirstName&gt;Jonathan&lt;/FirstName&gt;
 
    &lt;qualification&gt;5&lt;/qualification&gt;
 
    &lt;FoodPref picture="dolores_002.jpg"&gt;Asian&lt;/FoodPref&gt;
 
  ......
 
  &lt;/participant&gt;
 
 
 
===== Part of XSLT (file: participants.xsl) =====
 
��
 
&lt;xsl:template match="participants"&gt;
 
    &lt;table border="2" cellspacing="1" cellpadding="6"&gt;
 
    &lt;tr&gt;&lt;th&gt;Qualification&lt;/th&gt;
 
        &lt;th&gt;First Name&lt;/th&gt;
 
        &lt;th&gt;Description&lt;/th&gt;
 
        &lt;th&gt;Food Picture&lt;/th&gt;
 
      &lt;/tr&gt;
 
      &lt;xsl:for-each ''select="participant"''
&gt;
 
        ''&lt;xsl:sort''
  ''select="qualification"''
/&gt;
 
      &lt;tr&gt;
 
      &lt;td&gt;&lt;xsl:value-of select="qualification"/&gt;&lt;/td&gt;
 
      &lt;td&gt;&lt;xsl:value-of select="FirstName"/&gt;&lt;/td&gt;
 
      &lt;td&gt;&lt;xsl:value-of select="description"/&gt;&lt;/td&gt;
 
        &lt;td&gt;&lt;xsl:if test="FoodPref/@picture"&gt;
 
            &lt;img src="{FoodPref/@picture}"/&gt;&lt;/xsl:if&gt;&lt;/td&gt;
 
      &lt;/tr&gt;
 
      &lt;/xsl:for-each&gt;
 
    &lt;/table&gt;
 
&lt;/xsl:template&gt;
 
 
 
== 7. Moving on ==
 
* XSLT is a full programming language, but further XSLT constructs are out of scope for this class......
* Just for your information, I present a small example that demonstrates function calls.
 
 
 
==== Example 7-1: Display ingredients with increasing fonts ====
 
 
 
===== XML (file: ingredient-list2.xml) =====
 
&lt;ingredients&gt;  &lt;item&gt;3 taco shells&lt;/item&gt;&lt;item&gt;1 pkg hamburger 100g&lt;/item&gt;
 
  &lt;item&gt;Taco mix&lt;/item&gt; &lt;item&gt;50 g of cheese&lt;/item&gt;  &lt;item&gt;1 tomato&lt;/item&gt;
 
  &lt;item&gt;1 carot&lt;/item&gt; &lt;item&gt;Lettuce&lt;/item&gt;&lt;/ingredients&gt;
 
 
 
===== XSLT (file ingredient-list2.xsl) =====
 
&lt;xsl:template match="/ingredients"&gt;
 
  &lt;html&gt;
 
  &lt;head&gt; &lt;title&gt;Ingrediant list&lt;/title&gt; &lt;/head&gt;
 
    &lt;body bgcolor="#ffffff"&gt;
 
      Here is a list of recipe ingrediants:
 
      &lt;xsl:for-each select="item"&gt;
 
        &lt;xsl:''call-template''
  name="''display_item''
"&gt;
 
          &lt;xsl:''with-param''
  name="''position''
" select="position()"/&gt;
 
        &lt;/xsl:call-template&gt;
 
      &lt;/xsl:for-each&gt;
 
    &lt;/body&gt;
 
  &lt;/html&gt;
 
&lt;/xsl:template&gt;
 
&lt;!-- you can change the value of these 2 parameters --&gt;
 
  &lt;''xsl:param''
  name="''initial_size''
" select="5"/&gt;
 
  &lt;''xsl:param''
  name="''multiplier''
" select="3"/&gt;
 
  ��
 
&lt;xsl:''template name''<nowiki>
="</nowiki>''display_item''
"&gt;
 
  &lt;xsl:''param''
  name="''position''
"/&gt;
 
  &lt;xsl:''variable''
  name="font_size"
 
                select="$initial_size  $position * $multiplier"/&gt;
 
  &lt;xsl:''variable''
  name="color"&gt;
 
    &lt;xsl:choose&gt;
 
      &lt;xsl:when test="$position mod 3 = 0"&gt;
 
            &lt;xsl:text&gt;yellow&lt;/xsl:text&gt;&lt;/xsl:when&gt;
 
      &lt;xsl:when test="$position mod 3 = 1"&gt;
 
            &lt;xsl:text&gt;red&lt;/xsl:text&gt;  &lt;/xsl:when&gt;
 
      &lt;xsl:when test="$position mod 3 = 2"&gt;
 
            &lt;xsl:text&gt;blue&lt;/xsl:text&gt;  &lt;/xsl:when&gt;
 
      &lt;xsl:otherwise&gt;&lt;xsl:text&gt;green&lt;/xsl:text&gt;&lt;/xsl:otherwise&gt;
 
    &lt;/xsl:choose&gt;
 
  &lt;/xsl:''variable''
&gt;
 
  &lt;p style="color:{$color}; font-size: {$font_size}pt;"&gt;
 
      &lt;xsl:value-of select="."/&gt;&lt;br /&gt;
 
  [Pos = &lt;xsl:value-of select="$position"/&gt;,
 
    Multip. = &lt;xsl:value-of select="$multiplier"/&gt;,
 
    Font size = &lt;xsl:value-of select="$font_size"/&gt;] &lt;/p&gt;
 
&lt;/xsl:template&gt;
 
��
 
 
 
== 8. Next steps ==
 
 
 
=== 8.1 Reading ===
 
Carey (pp. 297-317, 317-335)
 
Optional: 1 or 2 case problems
 
 
 
=== 8.2 Next modules ===
 
 
 
===== Module 7 =====
 
* XML Schema
 
 
 
== 9. Homework: mini-project 6 ==
 
Due: Monday Feb. 19 16:00h
 
 
 
=== 9.1 Task ===
 
 
 
===== Create an XSLT transformation to (X)HTML. =====
 
* Create a DTD and a valid XML example file
* Translate the XML document to somewhat valid HTML or XHTML
* Write some user documentation (i.e. make sure others could use your DTD and stylesheet)
* Make use of some more advanced XPath and XSLT constructs (but be '' reasonable'' !!!)
* Take into account critique for homework 5
* You may reuse materials from previous homework
** I strongly suggest to base this project on homework 5 (XSLT)
 
 
 
=== 9.2 Approximate evaluation grid ===
 
 
 
===== Minimal requirement: =====
 
{| border="1"
! rowspan="1" colspan="1" |
Features
! rowspan="1" colspan="1" |
Expect a
|-
| rowspan="1" colspan="1" |
Valid XML (DTD) and well-formed XSLT style sheet that does a translation
| rowspan="1" colspan="1" |
D
|-
| rowspan="1" colspan="1" |
An XML contents that displays as (X)HTML in a web browser of your choice
| rowspan="1" colspan="1" |
C
|}
 
 
 
===== You will get extra points for =====
 
{| border="1"
! rowspan="1" colspan="1" |
Extra features
! rowspan="1" colspan="1" |
Extra points ( /- quality)
|-
| rowspan="1" colspan="1" |
Inserted comments &lt;!-- ... --&gt; in the various files (XML, XSLT or CSS)
| rowspan="1" colspan="1" |
 
|-
| rowspan="1" colspan="1" |
XML data organization that is appropriate for your domain
| rowspan="1" colspan="1" |
 
|-
| rowspan="1" colspan="1" |
Complexity of style sheet (kinds of transformations)
| rowspan="1" colspan="1" |
...
|-
| rowspan="1" colspan="1" |
Ergonomic and nice presentation (style and function)
| rowspan="1" colspan="1" |
...
|-
| rowspan="1" colspan="1" |
Your result document is valid HTML or XHTML
| rowspan="1" colspan="1" |
 
|-
| rowspan="1" colspan="1" |
A 1-2 page '' user manual'' that explains a user how to use your DTD and stylesheet
| rowspan="1" colspan="1" |
...
|-
| rowspan="1" colspan="1" |
A 1 page report that discusses your implementation
| rowspan="1" colspan="1" |
...
|}
 
* To get a B: Produce a useful (X)HTML document from valid XML
* To get an A:
** Create a useful DTD, an ergonomic XSLT, a useful manual and a report
** Alternatively: Create a really difficult XSLT and a good report
 
===== Submission format =====
 
I require a double submission:
 
# Paper copies to be turned in a start of Monday lesson
# Electronic copies to be uploaded to the server in folder homework/project_6 !!!<br /> Please make sure to name these documents according to the following rules:
 
your_name.xml or your_name.html or your_name.xhtml (mandatory)
 
your_name.dtd (optional)
 
your_name.{doc|pdf|html} Chose the format you like (optional)
 


----
Bad code:
: you forgot to use this ..


[none [[Image:next.gif|NEXT]]] -- [../../tie.html TIE]
Example fragment where position in a list is used to compute position on the screen with SVG in HTML5:
<source lang="XML">
<xsl:strip-space elements="list"/>
<xsl:template match="list">
    <rect x="10" y="105" width="{10 * count(item)}"
  height="5" fill="black" stroke="red"/>
    <xsl:apply-templates/>
</xsl:template>
</source>
Live example:
* [http://tecfa.unige.ch/guides/svg/ex/html5-xslt/intro-html5.xml intro-html5.xml]


== links ==
== Links ==


=== Introductory tutorials ===
=== Introductory tutorials ===
Line 2,018: Line 893:
* [http://en.wikipedia.org/wiki/Xpath Xpath] (Wikipedia)
* [http://en.wikipedia.org/wiki/Xpath Xpath] (Wikipedia)
* [http://www.zvon.org/xxl/XPathTutorial/General/examples.html Zvon tutorial] (lots of examples)
* [http://www.zvon.org/xxl/XPathTutorial/General/examples.html Zvon tutorial] (lots of examples)
* [http://www.perfectxml.com/XPathDotNet.asp XPath for .NET Developers] by Darshan Singh


=== Other ===
=== Other ===
Line 2,025: Line 901:


[[Category: XML]]
[[Category: XML]]
[[Category: Technologies]]
[[Category: databases]]
[[Category: databases]]
[[Category: Tutorials]]

Latest revision as of 17:29, 22 August 2016

Introduction

XPath is a language for addressing parts of an XML document. Basic understanding of XPath is needed for XSLT and XQuery programming. In this piece, we shall show how to create XSLT stylesheets that use some moderately complex XPath expressions

Tip: Read the free O'Reilly book: http://commons.oreilly.com/wiki/index.php/XPath_and_XPointer

Learning Objectives

  • Understand how to use XPath expressions, in order use XSLT and XQuery more effectively
  • Learn some XSLT programming constructions (conditions and loops)
  • Being able to cope with most XML to HTML transformations

Prerequisites

Next steps

Materials

  • We use the same XML document in most examples. You can download the file or look at a wiki page:
xpath-jungle.xml
XPath tutorial - basics/XML example code

Disclaimer

  • This is an unfinished, not very nice, introductory XPath tutorial. Cut/paste from slides with a few fixes. It needs more work, since right now it's more like a list of XPath features ... - Daniel K. Schneider
  • There may be typos (sorry) and mistakes (sorry again)

Introduction to XML Path Language

Definition and history

XPath is a language for addressing parts of an XML document, In support of this primary purpose, it also provides basic facilities for manipulation of strings, numbers and booleans.

Its 2.0 editition was described as “XPath 2.0 is an expression language that allows the processing of values conforming to the data model defined in XQuery/XPath Data Model (XDM). The data model provides a tree representation of XML documents as well as atomic values such as integers, strings, and booleans, and sequences that may contain both references to nodes in an XML document and atomic values. The result of an XPath expression may be a selection of nodes from the input documents, or an atomic value, or more generally, any sequence allowed by the data model. The name of the language derives from its most distinctive feature, the path expression, which provides a means of hierarchic addressing of the nodes in an XML tree.” (XML Path Language (XPath) 2.0 ,W3C Recommendation 23 January 2007, retrieved 16:38, 9 February 2010 (UTC).

  • XPath uses a compact non-XML syntax (to facilitate use of XPath within URIs and XML attribute values).
  • XPath gets its name from its use of a path notation as in URLs for navigating through the hierarchical structure of an XML document.
  • XPath was defined at the same time as XSLT (nov 1999)
  • Initally, it was developped to support XSLT and XPointer (XML Pointer Language used for XLink, XInclude, etc.). Today it is also used by XQuery and other applications. Many programming languages support an XPath library, e.g. PHP5.

In plain English, XPath allows retrieving parts of an XML document. XPath expressions can be as simple as the name of an XML element or so complicated that only experts can understand it ....

Specifications

XPath 1.0 is used by XSLT 1.0, i.e. the XSLT processor included in virtually every web browser as of Jan 2010 and since the early 2000's in IE/Mozilla.

XPath 2.0 is a superset of XPath 1.0 and is used by XSLT 2.0, XQuery and other specifications.

Reference manuals

XSLT, XQuery and XPath

Each time a given XSLT or XQuery instruction needs to address (refers to) parts of an XML document, we use XPath expressions. XPath expressions also can contain functions, simple math and boolean expressions.

Within XSLT, XPath expressions are typicially used in match, select and test attributes:

Xpath expressions in an XSLT template

Below is an XQuery example taken from the XQuery tutorial - basics

for $t in fn:doc("catalog09.xml")//c3msbrick
let $n := count($t//c3mssoft)
where ($n > 1)
order by $n
return <result> {$t/title/text()} owns {$n} bricks </result>

Playtime

Most XML editors will display the XPath of a selected element. In addition, you can search with XPath expressions, i.e. test an expression that you then would use in your XSLT or XQuery code.

Below is a screenshot of the XML Exchanger editor. As you can see we entered the //participant expression in the search box. The result is a so-called node-set that is displayed in the XPath pane at the bottom.

Xpath seach in the Exchanger editor

The XPath Syntax and the document model

Xpath Syntax

XPath expressions can be quite simple or very complex. An Xpath expression may include a location path (i.e. "where to look for"), node tests (i.e. identifying a node) and predicates(i.e. additional tests).

There are two notations for location paths.

(1) abbreviated

This simple notation allows to locate itself, children, parents, attributes and combinations of these. Going up or down is called an axis. The abbreviated form has limited axis.

para means "all "para" child elements of the current context

(2) unabbreviated

Unabbreviated location path allows to search in more axis then just parents, children, and siblings.

child::para" is identical to para above.

The abbreviated location path look a bit like file paths. E.g. the following expression:

/section/title

means: find all title nodes below section nodes

Syntax overview of the primary (relatively simple) XPath expressions

The picture below is not entirely correct, i.e. the "green" elements are part of the so called node-test Xml-xpath-3.png

The result of an Xpath expression can be various data types, e.g. sets of nodes, a single node, a number, etc. Most often the result, is a set of nodes.


The formal specification of an XML Path
  • is very complex, i.e. has about 39 clauses and is very difficult to understand
  • Some expressions shown here are beyond the scope of this tutorial, don't panic !

The document model of XPath

  • XPath sees an XML document as a tree structure
  • Each information (XML elements, attributes, text, etc.) is called a node. This is fairly similar to the W3C DOM model an XML or XSLT processor would use.
Nodes that XPath can see
  • root node
    • ATTENTION: The root is not necessarily the XML root element. E.g. processing instructions like a stylesheet declaration are also nodes.
  • Elements and attributes
  • Special nodes like comments, processing instructions, namespace declarations.
Nodes XPath can't see
  • XPath looks at the final document, therefore it can't see entities and document type declarations....
The XML context
  • What a given XPath expression means, is always defined by a given XML context, i.e. the current node in the XML tree a processor is looking at.

Using simple location path

Below, we present a few expressions for locating nodes using the simple abbreviated syntax. As we said before, location paths can be horribly complex, but simple location path look a bit like file path that you would use in HTML links or in an operating system like Unix, Windows or MacOS.

List of simple location path

Document root node - returns the document root (which is not necessarily the XML root!)
/
Direct child element
XML_element_name
Direct child of the root node
/XML_element_name
Child of a child
XML_element_name/XML_element_name
Descendant of the root
//XML_element_name
Descendant of a node
XML_element_name//XML_element_name
Parent of a node
../
A far cousin of a node
../../XML_element_name/XML_element_name/XML_element_name

Example - Extracting titles from an XML file with XSLT

Let us recall that we use the same XML document in most examples. You can download the file or look at a wiki page:

xpath-jungle.xml
XPath tutorial - basics/XML example code
<?xml version="1.0"?>
<project>
 <title>The Xpath project</title>
 <participants>
  <participant>
    <FirstName>Daniel</FirstName>
    <qualification>8</qualification>
    <description>Daniel will be the tutor</description>
    <FoodPref picture="dolores_001.jpg">Sea Food</FoodPref>
  </participant>
  <participant>
    <FirstName>Jonathan</FirstName>
    <qualification>5</qualification>
    <FoodPref picture="dolores_002.jpg">Asian</FoodPref>
  </participant>
  <participant>
   <FirstName>Bernadette</FirstName>
   <qualification>8</qualification>
    <description>Bernadette is an arts major</description>
  </participant>
  <participant>
   <FirstName>Nathalie</FirstName>
   <qualification>2</qualification>
  </participant>
 </participants>
 <problems>
  <problem>
    <title>Initial problem</title>
    <description>We have to learn something about Location Path</description>
    <difficulty level="5">This problem should not be too hard</difficulty>
  </problem>
  <solutions>
   <item val="low">Buy a XSLT book</item>
   <item val="low">Find an XSLT website</item>
   <item val="high">Register for a XSLT course and do exercices</item>
  </solutions>
   <problem>
    <title>Next problem</title>
    <description>We have to learn something about predicates</description>
    <difficulty level="6">This problem is a bit more difficult</difficulty>
  </problem>
  <solutions>
   <item val="low">Buy a XSLT book</item>
   <item val="medium">Read the specification and do some exercises</item>
   <item val="high">Register for a XPath course and do exercices</item>
  </solutions>
 </problems>
</project>
Task

We would like to get a simple list of problem titles

Solution

XSLT template (file: xpath-jungle-1.xsl

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">

  <xsl:output method="html"/>

  <xsl:template match="/project">
    <html>
      <body bgcolor="#FFFFFF">
        <h1><xsl:value-of select="title" /></h1>
        Here are the titles of our problems: <ul>
        <xsl:apply-templates select="problems/problem" /> 
      </ul>
      </body>
    </html>
  </xsl:template>

<xsl:template match="problems/problem">
  <li><xsl:value-of select="title" /></li>
</xsl:template>

</xsl:stylesheet>
(1) XSLT template for the root element
  • The XPath of the "match" means: apply the template to the project element node, which is a direct child of the root node
  • The execution context of this template is therefore the element "project"
  • The xsl:apply-templates expression will now tell the processor to find a rule for the problems/problem descendant.
(2) XSLT template for the problems/problem element

This second rule will be triggered by the first rule, because problems/problem is indeed a location that can be found in project element. The processor then can extract the value of the title element.

Alternatively we could have written this rule as:

<xsl:template match="problems/problem/title">
  <li><xsl:apply-templates/></li>
</xsl:template>

or

<xsl:template match="problems/problem/title">
  <li><xsl:value-of select="."/></li>
</xsl:template>
(3) Result HTML
 <html>
    <body bgcolor="#FFFFFF">
       <h1>The Xpath project</h1>
       Here are the titles of our problems:
       <ul>
          ''<li>Initial problem</li>''
          ''<li>Next problem</li>''
       </ul>
    </body>
 </html>

Live example:

Attribute Location Paths

Of course, XPath also also to locate attributes. We shall show the principle, using a few examples.

(1) To find an attribute of a child element in the current context use:

@attribute_name

Example:

@val

(2) Find attributes of an element in a longer location path starting from root

/element_name/element_name/@attribute_name

Example:

/project/problems/solutions/item/@val

(3) Find attributes in the whole document: //@attribute_name

As you can see you can combine element location with attribute identification.

Example - Create an html img link from an attribute

XML fragment

Same as above

Task

Display a list of First Names plus their food preferences

XSLT (File xpath-jungle-2.xsl
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">

  <xsl:output method="html"/>

  <xsl:template match="/">
    <html>
      <body bgcolor="#FFFFFF">
        <h1>What do we know about our participants ?</h1>
        Here are some food preferences: <ul>
        <xsl:apply-templates select=".//participant" /> 
      </ul>
      </body>
    </html>
  </xsl:template>

<xsl:template match="participant">
  <li><xsl:value-of select="FirstName"/>
  <xsl:apply-templates select="FoodPref"/>
  </li>
</xsl:template>

<xsl:template match="FoodPref">
  prefers <xsl:value-of select="."/>. 
  <img src="{@picture}"/> <br clear="all"/>
</xsl:template>

</xsl:stylesheet>
  • The second rule will display names of participants and launch a template for FoodPref
  • Note: Not all participants have a FoodPref element. If it is absent it will just be ignored.
  • The third rule (FoodPref) displays the text (contents) of FoodPref and then makes an HTML img tag


Parts of the result
   <h1>What do we know about our participants ?</h1>
       Here are some food preferences:
       <ul>
          <li>Daniel prefers Sea Food.
             <img src="dolores_001.jpg"><br clear="all"></li>
          <li>Jonathan
             prefers Asian.
             <img src="dolores_002.jpg"><br clear="all"></li>
          <li>Bernadette</li>
          <li>Nathalie</li>
       </ul>

Live example:

Location wildcards

  • Sometimes (but not often!), it is useful to work with wildcards
  • You have to understand that only one rule will be applied per element. Rules with wildcards have less priority and btw. this is why "your rules" are applied before the system default rules.
Find all child nodes of type XML element
*
Find all child nodes (including comments, etc.)
node()
Find all element attributes
@*
Find all text nodes
text()
Combine locations
use the "|" operator, an example is just below.

Example: XSLT includes two built-in default rules. They rely on using these wildcards.

This rule applies to the document root and all other elements

 <xsl:template match="*|/">
   <xsl:apply-templates/>
 </xsl:template>

Text and attribute values are just copied

 <xsl:template match="text()|@*">
   <xsl:value-of select="."/>
 </xsl:template>

XPaths with predicates

Let us now scale up a bit.

  • A predicate is an expression that can be true or false
  • It is appended within [...] to a given location path and will refine results
  • More than one predicate can be appended to and within (!) a location path
  • Expressions can contain mathematical or boolean operators
Find element number N in a list
Syntax: XML_element_name [ N ]
/project/participants/participant[2]
/project/participants/participant[2]/FirstName
Find elements that have a given attribute
Synatx: XML_element_name [ @attribute_name ]
//difficulty[@level]
Find elements that have a given element as child
Syntax XML_element_name [ XML_element_name ]//participant[FoodPref]
Note: this is not the same as //participant/FoodPref. The latter would return a list of FoodPref elements, whereas the former returns a list of participant
Mathematical expressions
  • Use the standard operators, except div instead of / (for obvious reasons)
- * div mod
  • mod is interesting if you want to display a long list in table format
5 mod 2 returns 1, as will "7 mod 2" and "3 mod 2"
Boolean operators (comparison, and, or)
  • List of operators (according to precedence)
<=, <, >=, >
=, !=
and, or


Examples
  • Return all exercise titles with a grade bigger than 5.
//exercise[note>5]/title
  • Find elements that have a given attribute with a given value
Recall of the Syntax: XML_element_name [ @attribute_name="value"]
//solutions/item[@val="low"]
  • Example XSLT template that will match all item elements with val="low".
<xsl:template match="'//item[@val='low']">
    <xsl:value-of select="." />
</xsl:template>

Usually expressions also contain functions as we shall see below, examples:

  • Return the last five elements of a list
author [(last() - 4) <= position()) and (position() <= last())]
  • Return all Participant nodes with a contents of FirstName bigger than 7 characters:
"//Participant[string-length(FirstName)>=8]"

Example: Retrieve selected elements

The following example will retrieve the following:

  • All persons who do have a food preference
  • All items that have an a "priority" attribute set to "high"
The XSLT stylesheet (file xpath-jungle-3.xsl)
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">

  <xsl:output method="html"/>

  <xsl:template match="/">
    <html>
      <body bgcolor="#FFFFFF">
        <h1>Retrieve selected elements</h1>
        Here is the name of participant two: 
        <ul><li><xsl:value-of select=".//participant[2]/FirstName"/></li></ul>
        Here are all participant's firstnames that have a food preference: 
        <ul><xsl:apply-templates select=".//participant[FoodPref]"/></ul>
        Here are all items that have a value of "high"
        <ul><xsl:apply-templates select=".//item[@val='high']"/></ul>
      </body>
    </html>
  </xsl:template>

<xsl:template match="participant">
  <li><xsl:value-of select="FirstName"/></li>
</xsl:template>

<xsl:template match="item">
  <li><xsl:value-of select="."/></li>
</xsl:template>

</xsl:stylesheet>
HTML result
<html>
   <body bgcolor="#FFFFFF">
      <h1>Retrieve selected elements</h1>
      Here is the name of participant two:
      <ul>
         <li>Jonathan</li>
      </ul>
      Here are all participant's firstnames that have a food preference:
      <ul>
         <li>Daniel</li>
         <li>Jonathan</li>
      </ul>
      Here are all items that have a value of "high"
      <ul>
         <li>Register for a XSLT course and do exercices</li>
         <li>Register for a XPath course and do exercices</li>
      </ul>
   </body>
</html>

Live example:

Below is a more complex example. One in short notation and the other (to do) in it equivalent long notations:

/outputTree/command/pivotTable/dimension//category[@text='Measurement']/dimension/category/cell[@text='Nominal']


XPath functions

XPath defines a certain number of functions. You can recognize a function because it has appended "()".

Functions are programming constructs that will return various kinds of informations, e.g.

  • true / false
  • a number
  • a string
  • a list of nodes

It is not obvious to understand what all of these functions do. For example, there are restrictions on how you can use functions (stick to examples or the reference)

last()
last() gives the number or nodes within a context
position()
position() returns the position of an element with respect to other children in the same parent
Warning: The result will include empty nodes create from whitespaces between elements. To avoid this you should strip the parent nodes using
 <xsl:strip-space elements="name_of_the_parent_node"/>
count(node-set)
count gives the number of nodes in a node set
We got <xsl:value-of select="count(//problem)"/> problems, 
i.e. it will count N elements retrieved and not the child elements of problem
Live example: xpath-jungle-6.xml - xpath-jungle-6.xsl
starts-with(string, string)
returns TRUE if the second string is part of the first and starts off the first
//Participant[starts-with(Firstname,'Berna')]"
contains(string, string)
returns TRUE if the second string is part of the first
//Participant[contains(FirstName,'nat')]
string-length(string)
returns the length of a string
number(string)
transforms a string into a number
sum(node-set)
computes the sum of a given set of nodes.
If necessary, does string conversion with number()
round(number)
round a number, e.g. 1.4 becomes 1 and 1.7 becomes 2
translate(string1, string2, string3)
translates string1 by substituting string2 elements with string3 elements

Example: Computation of an average

  • We would like to compute the average of participant's qualifications
 <participant><FirstName>Daniel</FirstName>
              ''<qualification>8</qualification>''
    </participant>
The XSLT stylesheet (file xpath-jungle-4.xsl
  • We compute the sum of a node-set and then divide by the number of nodes
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">

  <xsl:output method="html"/>

  <xsl:template match="/">
    <html>
      <body bgcolor="#FFFFFF">
        <h1>Qualification level of participants</h1>
        Average is
        <xsl:value-of select="sum(.//participant/qualification) div count(.//participant/qualification)"/>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>
HTML result
 <html>
    <body bgcolor="#FFFFFF">
       <h1>Qualification level of participants</h1>
       Average is
       5.75
    </body>
 </html>

Live example:

Example: Find first names containing 'nat'

The XSLT stylesheet (file xpath-jungle-5.xsl
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">

  <xsl:output method="html"/>

  <xsl:template match="/">
    <html>
      <body bgcolor="#FFFFFF">
        <h1>Do we have a "nat" ?</h1>
        First Names that contain "nat":
        <ul><xsl:apply-templates select=".//participant[contains(FirstName,'nat')]"/></ul>
        First Names that contain "nat" and "Nat":
        <ul><xsl:apply-templates select=".//participant[contains(translate(FirstName,'N','n'),'nat')]"/></ul>
      </body>
    </html>
  </xsl:template>

<xsl:template match="participant">
  <li><xsl:value-of select="FirstName"/></li>
</xsl:template>

</xsl:stylesheet>

Live example

Union of XPaths

Union Xpaths combine more than one XPath (and all the resulting nodes are returned). A typical example that we already introduced above is the default rule which means that the template matches either the root element (i.e. "/" or just any element),

 <xsl:template match="*|/">
   <xsl:apply-templates/>
 </xsl:template>

Often, this construct is used to simplify apply-templates or even templates themselves. E.g. the following rules applies to both "description" and "para" elements.

 <xsl:template match="para|description">
   <p><xsl:apply-templates/></p>
 </xsl:template>

List of commonly used XPath expressions

Syntax
element

(Type of path)

Example path

Example matches

name

child element name

project

<project> ...... </project>

/

child / child

project/title

<project> <title> ... </title>

/

(root element)

//

descendant

project//title

<project><problem> <title>....</title>

//title

<root>... <title>..</title> (any place)

*

"wildcard"

*/title

<bla> <title>..</title> and <bli> <title>...</title>

|

"or operator

title|head

<title>...</title> or <head> ...</head>

*|/|@*

All elements: root, children and attributes

.

current element

.

../

parent element

../problem

<project>

@attr

attribute name

@id

<xyz id="test">...</xyz>

element/@attr

attribute of child

project/@id

<project id="test" ...> ... </project>

@attr='value'

value of attribute

list[@type='ol']

<list type="ol"> ...... </list>

position()

position of element
in parent

position()

last()

number of elements within a context

last()

position()!=last()


Important:

  • The XML standard requires that an XML parser returns emtpy space between elements as empty nodes. In other words, functions such as location() or last() will also count empty nodes ! Tell XSLT to remove these within the elements within which you need to count.

Good code:

<xsl:strip-space elements="name_of_the_parent"/>

Bad code:

you forgot to use this ..

Example fragment where position in a list is used to compute position on the screen with SVG in HTML5:

<xsl:strip-space elements="list"/>
<xsl:template match="list">
    <rect x="10" y="105" width="{10 * count(item)}" 
	  height="5" fill="black" stroke="red"/>
    <xsl:apply-templates/>
</xsl:template>

Live example:

Links

Introductory tutorials

Other