What is XML?
XML is a framework for defining markup languages:
l there is no fixed collection of markup tags;
l each XML language is targeted at different application domains;
l the languages will share many features;
l there is a common set of tools for processing such languages.
XML is not a replacement for HTML:
l HTML should ideally be just another XML language;
l in fact, XHTML is just that;
l XHTML is a (very popular) XML language for hypertext markup.
XML is designed to:
l seperate syntax from semantics;
l support internationalization (Unicode) and platform independence;
l be the future of structured information, including databases.
HTML vs. XML
Consider the following recipe collection published in HTML:
<h1>Rhubarb Cobbler</h1>
<h2>Maggie.Herrick@bbs.mhv.net</h2>
<h3>Wed, 14 Jun 95</h3>
Rhubarb Cobbler made with bananas as the main sweetener.
It was delicious. Basicly it was
<table>
<tr><td> 2 1/2 cups <td> diced rhubarb (blanched with boiling
water, drain)
<tr><td> 2 tablespoons <td> sugar
<tr><td> 2 <td> fairly ripe bananas sliced 1/4" round
<tr><td> 1/4 teaspoon <td> cinnamon
<tr><td> dash of <td> nutmeg
</table>
Combine all and use as cobbler, pie, or crisp.
Related recipes: <a href="#GardenQuiche">Garden Quiche</a>
There are many problems with this approach:
l the semantics is encoded into text formatting tags;
l there is no means of checking that a recipe is encoded correctly;
l it is difficult to change the layout of recipes (CSS is not enough).
It would be much better to invent a special recipe markup language:
<recipe id="117" category="dessert">
<title>Rhubarb Cobbler</title>
<author><email>Maggie.Herrick@bbs.mhv.net</email></author>
<date>Wed, 14 Jun 95</date>
<description>
Rhubarb Cobbler made with bananas as the main sweetener.
It was delicious.
</description>
<ingredients>
...
</ingredients>
<preparation>
Combine all and use as cobbler, pie, or crisp.
</preparation>
<related url="#GardenQuiche">Garden Quiche</related>
</recipe>
This example illustrates:
l the markup tags are chosen purely for logical structure;
l this is just one choice of markup detail level;
l we need a kind of "grammar" for XML recipe collections;
l we need a stylesheet to define presentation semantics.
A conceptual view of XML
An XML document is a labeled tree.
a leaf node is
m character data (a text string) - the actual data,
a processing instruction - annotations for various processors, typically in document
header,
m
m a comment - never any semantics attached,
m an entity declaration - simple macros.
l
an internal node is an element, which is labeled with
m a name, and
m a set of attributes, each consisting of a name and a value.
l
A concrete view of XML
An XML document is a (Unicode) text with markup tags and other meta-information.
Markup tags denote elements:
...<foo attr="val" ...>...</foo>...
| | | |
| | | a matching element end tag
| | the contents of the element
| an attribute with name attr and value val, values enclosed by ' or "
an element start tag with name foo
There is a short-hand notation for empty elements: ...<foo attr="val".../>...
Note: XML is case sensitive!!
An XML document must be well-formed:
l start and end tags must match;
l element tags must be properly nested;
l and some more subtle syntactical requirements.
Special characters can be escaped using Unicode character references:
l & yields &;
l < and < both yield <.
CDATA Sections are an alternative to escaping many characters:
l <![CDATA[<greeting>Hello, world!</greeting>]]>
The strange syntax is a legacy from SGML...
The following service checks well-formedness of an XML document (given a full URL):
Applications of XML
There are already hundreds of serious applications of XML.
XHTML
W3C's XMLization of HTML 4.0. Example XHTML document:
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head><title>Hello world!</title></head>
<body><p>foobar</p></body>
</html>
CML
Chemical Markup Language. Example CML document snippet:
<molecule id="METHANOL">
<atomArray>
<stringArray builtin="elementType">C O H H H H</stringArray>
<floatArray builtin="x3" units="pm">
-0.748 0.558 -1.293 -1.263 -0.699 0.716
</floatArray>
</atomArray>
</molecule>
WML
Wireless Markup Language for WAP services:
<?xml version="1.0"?>
<wml>
<card id="Card1" title="Wap-UK.com">
<p>
Hello World
</p>
</card>
</wml>
There is a long list of many other XML applications.
XML technologies
Just a notation for trees is not enough:
l the real force of XML is generic languages and tools!
The XML vision offers:
namespaces
- to avoid name clashes when a document uses several "sub-languages";
schemas
- grammars to define classes of documents;
linking between documents
- a generalization of HTML anchors and links;
addressing parts of documents
- it is not enough that only the author can place anchors;
transformation
- conversion from one document class to another;
querying
- extraction of information.
Namespaces
Consider an XML language WidgetML which uses XHTML as a sublanguage for help messages:
<widget type="gadget">
<head size="medium"/>
<big><subwidget ref="gizmo"/></big>
<info>
<head>
<title>Description of gadget</title>
</head>
<body>
<h1>Gadget</h1>
A gadget contains a big gizmo
</body>
</info>
</widget>
We have some problems here:
l the meaning of head and big depends on the context;
l this complicates things for processors and might even cause ambiguities;
l the root of the problem is: one common name-space.
The solution is to introduce explicit namespace declarations:
<widget xmlns="http://www.widget.org"
xmlns:xhtml="http://www.w3.org/TR/xhtml1"
type="gadget">
<head size="medium"/>
<big><subwidget ref="gizmo"/></big>
<info>
<xhtml:head>
<xhtml:title>Description of gadget</xhtml:title>
</xhtml:head>
<xhtml:body>
<xhtml:h1>Gadget</xhtml:h1>
A gadget contains a big gizmo
</xhtml:body>
</info>
</widget>
Do not be confused by the use of URI for namespaces:
l they are not supposed to point to anything;
l it is simply the cheapest way of getting unqiue names;
l we rely on existing organizations that control domain names.
All XML technologies (are supposed to) respect namespaces.
The recipe example
Consider the following raw data describing some (Danish) recipes:
l citrontærte;
l farsbrød;
l hornfisk;
l islagkage;
l laksemousse;
l nougattoppe;
l rabarberdessert;
l smørrebrød.
We can represent this collection as an XML document.
Schema languages
The syntax of a new XML language must be formalized:
l this is similar to the formal syntax of a programming language;
l however, usual context-free grammars are not expressive enough;
l XML languages are described using schemas.
A modern schema language:
l is itself an XML language (and can be used to describe itself);
l imposes constraints on the contents of elements;
l is context-sensitive and very fine-grained;
l can be processed efficiently.
A schema processor:
l checks that an application document satisfies the schema;
l such a document is called valid.
A schema for recipes
The following is a complete schema for the recipe example, written in the DSD schema language:
<?xml version="1.0" encoding="UTF-8"?>
<?dsd URI="http://www.brics.dk/DSD/dsd.dsd"?>
<DSD IDRef="opskriftsamling" DSDVersion="1.0">
<ElementDef ID="opskriftsamling">
<Optional><Element IDRef="beskrivelse"/></Optional>
<ZeroOrMore><Element IDRef="opskrift"/></ZeroOrMore>
</ElementDef>
<ElementDef ID="beskrivelse">
<Content IDRef="hvadsomhelst"/>
</ElementDef>
<ContentDef ID="hvadsomhelst">
<ZeroOrMore>
<Union >
<StringType/><AnyElement/>
</Union>
</ZeroOrMore>
</ContentDef>
<ElementDef ID="titel">
<Content IDRef="hvadsomhelst"/>
</ElementDef>
<ElementDef ID="opskrift">
<AttributeDecl Name="kvantitet" Optional="no"/>
<AttributeDecl Name="tid" Optional="yes"/>
<Sequence>
<Element IDRef="titel"/>
<Content IDRef="indhold"/>
<Optional>
<Element Name="garniture">
<Content IDRef="hvadsomhelst"/>
</Element>
</Optional>
<Optional>
<Element Name="servering">
<Content IDRef="hvadsomhelst"/>
</Element>
</Optional>
<Optional>
<Element Name="tips">
<Content IDRef="hvadsomhelst"/>
</Element>
</Optional>
<Element Name="energi">
<AttributeDecl Name="kjoule" Optional="no"/>
<AttributeDecl Name="fedt" Optional="no">
<StringType IDRef="tal"/>
</AttributeDecl>
<AttributeDecl Name="kulhydrat" Optional="no">
<StringType IDRef="tal"/>
</AttributeDecl>
<AttributeDecl Name="protein" Optional="no">
<StringType IDRef="tal"/>
</AttributeDecl>
<AttributeDecl Name="alkohol" Optional="yes">
<StringType IDRef="tal"/>
</AttributeDecl>
</Element>
</Sequence>
</ElementDef>
<ContentDef ID="indhold">
<Sequence>
<OneOrMore>
<Element IDRef="ingrediens"/>
</OneOrMore>
<Element Name="tilberedning">
<Content IDRef="hvadsomhelst"/>
</Element>
</Sequence>
</ContentDef>
<ElementDef ID="ingrediens">
<AttributeDecl Name="navn" Optional="no"/>
<AttributeDecl Name="antal" Optional="yes">
<Union >
<String Value="*"/>
<StringType IDRef="tal"/>
</Union>
</AttributeDecl>
<AttributeDecl Name="enhed" Optional="yes"/>
<If><Attribute Name="antal"/>
<Then>
<Empty/>
</Then>
<Else>
<Not><Attribute Name="enhed"/></Not>
<Content IDRef="indhold"/>
</Else>
</If>
</ElementDef>
<StringTypeDef ID="cifre">
<OneOrMore>
<CharRange Start="0" End="9"/>
</OneOrMore>
</StringTypeDef>
<StringTypeDef ID="tal">
<Sequence>
<StringType IDRef="cifre"/>
<Optional>
<Sequence>
<String Value=","/>
<StringType IDRef="cifre"/>
</Sequence>
</Optional>
</Sequence>
</StringTypeDef>
</DSD>
XML: XLink, XPointer, and XPath
XLink, XPointer, and XPath are three related mechanisms:
l they generalize the link mechanisms from HTML;
l XPath points from without to a set of nodes in an XML document;
l XPointer uses XPath to directly generalize HTML links;
l XLink uses XPointer to vastly generalize HTML links.
HTML links are just too simple:
an anchor must be placed at every link destination (problem with read-only documents)
- we want to express relative locations;
l
the link definition must be at the same location as the link source
- we want out-of-line links ("link databases");
l
only individual nodes can be linked to
- we want links to whole tree fragments;
l
a link always has one source and one destination
- we want links with multiple sources and destinations.
l
The XLink pointer model looks like this:
These technologies are not really supported by any browsers today.
Pointing at recipes
The following simple XPath expressions point to parts of the XML recipe document:
//ingrediens[@navn="radiser i små tern"]/@antal
200
//ingrediens[@antal="100" and @enhed="g"]/@navn
flødeost med løg og urter
blødt smør i mindre stykker
Feta ost 45+
smeltet overtrækschokolade
//titel[text()="Citrontærte"]
/following-sibling::ingrediens[@navn="dej"]/tilberedning/text()
Bland mel og sukker i en skål. Skær smørret i mindre stykker og
smuldr det i melblandingen, til den ligner revet ost. Tilsæt vand
og saml hurtigt dejen. Tryk den ud i en smurt springform (ca. 22 cm
i diameter). Lad dejen gå halvt op ad formens side. Stil den
tildækket i køleskabet i mindst 1 time. Forbag bunden midt i ovnen
i 12 minutter ved 200 grader.
XPath expressions navigate step by step through the XML tree.
XML-QL
XML-QL is a query language for XML documents:
l XML document can be seen as generalizations of database relations;
l XML-QL is a similar generalization of SQL;
l it can extract data from exisiting XML documents and construct new XML documents.
Relations are special, restricted cases of XML trees:
XML query languages are not released until 2001.
Querying the recipes
The following XML-QL queries extract information from the XML recipe document:
WHERE <opskriftsamling>
<opskrift>
<titel>$t</titel>
</opskrift>
</opskriftsamling>
IN "karoline.xml"
CONSTRUCT <titel>$t</titel>
<?xml version="1.0"?<
<XML>
<titel>Filokurve med tigerrejer</titel>
<titel>Laksemousse</titel>
<titel>Smørrebrød med flødeost og tomat</titel>
<titel>Citrontærte</titel>
<titel>Hornfisk med radisesalat</titel>
<titel>Islagkage med chokolade</titel>
<titel>Rabarberdessert med jordbær</titel>
<titel>Nougattoppe</titel>
<titel>Græsk farsbrød og agurkesalat</titel>
</XML>
CONSTRUCT <opskriftermedsukker> {
WHERE <opskriftsamling>
<opskrift>
<titel>$t</>
<ingrediens*>
<ingrediens navn="sukker"/>
</>
</opskift>
</opskriftsamling>
IN "karoline.xml"
CONSTRUCT <navn>$t</navn>
} </opskriftermedsukker>
<?xml version="1.0"?>
<opskriftermedsukker>
<navn>Citrontærte</navn>
<navn>Islagkage med chokolade</navn>
<navn>Rabarberdessert med jordbær</navn>
</opskriftermedsukker>
WHERE <*><ingrediens navn=$i/></> IN "karoline.xml"
CONSTRUCT
<ingrediens navn=$i>
{ WHERE <opskriftsamling>
<opskrift>
<titel>$t</titel>
<*>
<ingrediens navn=$i/>
</>
</opskrift>
</opskriftsamling>
IN "karoline.xml"
CONSTRUCT <ret>$t</ret>
}
</ingrediens>
<?xml version="1.0"?>
<XML>
<ingrediens navn="æggeblommer">
<ret>Islagkage med chokolade</ret>
</ingrediens>
<ingrediens navn="friskpresset citronsaft">
<ret>Laksemousse</ret>
<ret>Citrontærte</ret>
</ingrediens>
<ingrediens navn="jordbær i skiver">
<ret>Rabarberdessert med jordbær</ret>
</ingrediens>
<ingrediens navn="dej">
<ret>Citrontærte</ret>
</ingrediens>
<ingrediens navn="agurketern">
<ret>Græsk farsbrød og agurkesalat</ret>
</ingrediens>
<ingrediens navn="hornfisk">
<ret>Hornfisk med radisesalat</ret>
</ingrediens>
<ingrediens navn="yoghurt">
<ret>Græsk farsbrød og agurkesalat</ret>
</ingrediens>
<ingrediens navn="kvarkdressing">
<ret>Hornfisk med radisesalat</ret>
</ingrediens>
<ingrediens navn="sukker">
<ret>Citrontærte</ret>
<ret>Rabarberdessert med jordbær</ret>
<ret>Islagkage med chokolade</ret>
</ingrediens>
<ingrediens navn="radisesalat">
<ret>Hornfisk med radisesalat</ret>
</ingrediens>
<ingrediens navn="mellemstore æg">
<ret>Citrontærte</ret>
</ingrediens>
<ingrediens navn="rom">
<ret>Islagkage med chokolade</ret>
</ingrediens>
<ingrediens navn="vand">
<ret>Rabarberdessert med jordbær</ret>
<ret>Græsk farsbrød og agurkesalat</ret>
<ret>Citrontærte</ret>
</ingrediens>
<ingrediens navn="koldt smør">
<ret>Citrontærte</ret>
</ingrediens>
<ingrediens navn="hvedemel">
<ret>Citrontærte</ret>
</ingrediens>
<ingrediens navn="små papir- eller folieforme">
<ret>Nougattoppe</ret>
</ingrediens>
<ingrediens navn="fyld">
<ret>Græsk farsbrød og agurkesalat</ret>
</ingrediens>
<ingrediens navn="fars">
<ret>Græsk farsbrød og agurkesalat</ret>
</ingrediens>
<ingrediens navn="friskkværnet peber">
<ret>Laksemousse</ret>
<ret>Græsk farsbrød og agurkesalat</ret>
<ret>Hornfisk med radisesalat</ret>
</ingrediens>
<ingrediens navn="rabarber">
<ret>Rabarberdessert med jordbær</ret>
</ingrediens>
<ingrediens navn="agurkesalat">
<ret>Græsk farsbrød og agurkesalat</ret>
</ingrediens>
<ingrediens navn="bladselleri">
<ret>Laksemousse</ret>
</ingrediens>
<ingrediens navn="knust fed hvidløg">
<ret>Græsk farsbrød og agurkesalat</ret>
</ingrediens>
<ingrediens navn="piskefløde">
<ret>Nougattoppe</ret>
<ret>Islagkage med chokolade</ret>
<ret>Laksemousse</ret>
</ingrediens>
<ingrediens navn="frisk, hakket persille">
<ret>Græsk farsbrød og agurkesalat</ret>
</ingrediens>
<ingrediens navn="groft salt">
<ret>Laksemousse</ret>
<ret>Græsk farsbrød og agurkesalat</ret>
<ret>Filokurve med tigerrejer</ret>
<ret>Hornfisk med radisesalat</ret>
</ingrediens>
<ingrediens navn="husblas">
<ret>Laksemousse</ret>
</ingrediens>
<ingrediens navn="Feta ost 45+">
<ret>Græsk farsbrød og agurkesalat</ret>
</ingrediens>
<ingrediens navn="frisk, rød chilipeber">
<ret>Filokurve med tigerrejer</ret>
</ingrediens>
<ingrediens navn="tørret basilikum">
<ret>Smørrebrød med flødeost og tomat</ret>
</ingrediens>
<ingrediens navn="lille hakket zittauerløg">
<ret>Græsk farsbrød og agurkesalat</ret>
</ingrediens>
<ingrediens navn="smør">
<ret>Filokurve med tigerrejer</ret>
<ret>Græsk farsbrød og agurkesalat</ret>
</ingrediens>
<ingrediens navn="hakket hvidløgsfed">
<ret>Filokurve med tigerrejer</ret>
</ingrediens>
<ingrediens navn="creme fraiche">
<ret>Filokurve med tigerrejer</ret>
<ret>Laksemousse</ret>
</ingrediens>
<ingrediens navn="overtræk">
<ret>Islagkage med chokolade</ret>
</ingrediens>
<ingrediens navn="parfait">
<ret>Islagkage med chokolade</ret>
</ingrediens>
<ingrediens navn="smeltet overtrækschokolade">
<ret>Islagkage med chokolade</ret>
</ingrediens>
<ingrediens navn="agurk">
<ret>Filokurve med tigerrejer</ret>
</ingrediens>
<ingrediens navn="udbenet hornfisk">
<ret>Hornfisk med radisesalat</ret>
</ingrediens>
<ingrediens navn="makronbund">
<ret>Islagkage med chokolade</ret>
</ingrediens>
<ingrediens navn="olivenolie">
<ret>Filokurve med tigerrejer</ret>
</ingrediens>
<ingrediens navn="frisk, klippet purløg">
<ret>Hornfisk med radisesalat</ret>
</ingrediens>
<ingrediens navn="jordbærskiver">
<ret>Rabarberdessert med jordbær</ret>
</ingrediens>
<ingrediens navn="limefrugt i halve skiver">
<ret>Filokurve med tigerrejer</ret>
</ingrediens>
<ingrediens navn="creme fraiche 18%">
<ret>Hornfisk med radisesalat</ret>
</ingrediens>
<ingrediens navn="friske, hakkede citronmelisseblade">
<ret>Filokurve med tigerrejer</ret>
</ingrediens>
<ingrediens navn="kvark 5+">
<ret>Hornfisk med radisesalat</ret>
</ingrediens>
<ingrediens navn="frosne, optøede tigerrejer med halevifte">
<ret>Filokurve med tigerrejer</ret>
</ingrediens>
<ingrediens navn="agurk i små tern">
<ret>Hornfisk med radisesalat</ret>
</ingrediens>
<ingrediens navn="cherrytomater i skiver">
<ret>Smørrebrød med flødeost og tomat</ret>
</ingrediens>
<ingrediens navn="magert, hakket svinekød">
<ret>Græsk farsbrød og agurkesalat</ret>
</ingrediens>
<ingrediens navn="flødeost med løg og urter">
<ret>Smørrebrød med flødeost og tomat</ret>
</ingrediens>
<ingrediens navn="mælk">
<ret>Græsk farsbrød og agurkesalat</ret>
</ingrediens>
<ingrediens navn="groft knækbrød">
<ret>Smørrebrød med flødeost og tomat</ret>
</ingrediens>
<ingrediens navn="hakket lammekød">
<ret>Græsk farsbrød og agurkesalat</ret>
</ingrediens>
<ingrediens navn="friske citronmelisseblade">
<ret>Citrontærte</ret>
</ingrediens>
<ingrediens navn="ris">
<ret>Græsk farsbrød og agurkesalat</ret>
</ingrediens>
<ingrediens navn="frossen, optøet filodej">
<ret>Filokurve med tigerrejer</ret>
</ingrediens>
<ingrediens navn="citroncreme">
<ret>Citrontærte</ret>
</ingrediens>
<ingrediens navn="mellemstort æg">
<ret>Græsk farsbrød og agurkesalat</ret>
</ingrediens>
<ingrediens navn="smeltet smør">
<ret>Filokurve med tigerrejer</ret>
</ingrediens>
<ingrediens navn="majsstivelse">
<ret>Citrontærte</ret>
</ingrediens>
<ingrediens navn="parboiled ris">
<ret>Græsk farsbrød og agurkesalat</ret>
</ingrediens>
<ingrediens navn="blødt smør i mindre stykker">
<ret>Citrontærte</ret>
</ingrediens>
<ingrediens navn="iskold piskefløde">
<ret>Rabarberdessert med jordbær</ret>
</ingrediens>
<ingrediens navn="rababerkompot">
<ret>Rabarberdessert med jordbær</ret>
</ingrediens>
<ingrediens navn="jordbær">
<ret>Rabarberdessert med jordbær</ret>
</ingrediens>
<ingrediens navn="filokurve">
<ret>Filokurve med tigerrejer</ret>
</ingrediens>
<ingrediens navn="radiser i små tern">
<ret>Hornfisk med radisesalat</ret>
</ingrediens>
<ingrediens navn="mørk rom">
<ret>Nougattoppe</ret>
</ingrediens>
<ingrediens navn="finthakket bladselleri">
<ret>Laksemousse</ret>
</ingrediens>
<ingrediens navn="overtrækschokolade">
<ret>Islagkage med chokolade</ret>
</ingrediens>
<ingrediens navn="blød nougat">
<ret>Nougattoppe</ret>
</ingrediens>
<ingrediens navn="citronbåde">
<ret>Laksemousse</ret>
</ingrediens>
<ingrediens navn="vanillekorn">
<ret>Islagkage med chokolade</ret>
</ingrediens>
<ingrediens navn="laks">
<ret>Laksemousse</ret>
</ingrediens>
</XML>
XSLT
An XSLT style sheets transforms an XML document into another:
l if the target language is XHTML, then this is similar to a CSS style sheet;
l however, often the target language is really another XML language.
An XSLT style sheet:
l uses pattern matching and templates to specify the transformation;
l may perform arbitrary computations;
l is vastly more expressive than a CSS style sheet.
XSLT will be everywhere:
l browsers will only directly understand the XML language FO (formatting objects);
l HTML will be defined be a canonical XSLT style sheet into FO;
l many applications of XSLT will be involved in rendering a typical document.
There is little support for XSLT style sheets yet:
l Netscape 4 does nothing;
l Explorer 5 supports a subset of a deprecated syntax from 1998.
However, the following service correctly processes an XML document with an associated stylesheet
(given a full URL):
A style sheet for recipes
The following XSLT style sheet illustrates many features (the two namespaces are in different colors):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns="http://www.w3.org/1999/xhtml">
<xsl:template match="opskriftsamling">
<html>
<head>
<title><xsl:apply-templates select="beskrivelse"/></title>
</head>
<body>
<xsl:apply-templates select="opskrift"/>
</body>
</html>
</xsl:template>
<xsl:template match="beskrivelse">
<xsl:value-of select="text()"/>
</xsl:template>
<xsl:template match="opskrift">
<h1>
<xsl:value-of select="titel"/><xsl:text> </xsl:text>
(<xsl:value-of select="@kvantitet"/>)
</h1>
<ul>
<xsl:apply-templates select="ingrediens"/>
<xsl:apply-templates select="tilberedning"/>
</ul>
<xsl:apply-templates select="garniture"/>
<xsl:apply-templates select="servering"/>
<xsl:apply-templates select="tips"/>
<xsl:apply-templates select="energi"/>
<hr/>
</xsl:template>
<xsl:template match="ingrediens">
<xsl:choose>
<xsl:when test="@antal">
<li>
<xsl:if test="@antal!='*'">
<xsl:value-of select="@antal"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@enhed"/>
<xsl:text> </xsl:text>
</xsl:if>
<xsl:value-of select="@navn"/>
</li>
</xsl:when>
<xsl:otherwise>
<li><xsl:value-of select="@navn"/></li>
<ul>
<xsl:apply-templates select="ingrediens"/>
<xsl:apply-templates select="tilberedning"/>
</ul>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="tilberedning">
<xsl:if test="node() or text()">
<li>
<i>
<xsl:value-of select="text()|node()"/>
</i>
</li>
</xsl:if>
</xsl:template>
<xsl:template match="garniture">
<h3>Garniture</h3>
<xsl:value-of select="text()|node()"/>
</xsl:template>
<xsl:template match="servering">
<h3>Servering</h3>
<xsl:value-of select="text()|node()"/>
</xsl:template>
<xsl:template match="tips">
<h3>Tips</h3>
<xsl:value-of select="text()|node()"/>
</xsl:template>
<xsl:template match="energi">
<p/>
<table border="2">
<tr>
<th>kJoule</th><th>Fedt</th><th>Kulhydrat</th><th>Protein</th>
<xsl:if test="@alkohol">
<th>Alkohol</th>
</xsl:if>
</tr>
<tr>
<td align="right"><xsl:value-of select="@kjoule"/></td>
<td align="right"><xsl:value-of select="@fedt"/>%</td>
<td align="right"><xsl:value-of select="@kulhydrat"/>%</td>
<td align="right"><xsl:value-of select="@protein"/>%</td>
<xsl:if test="@alkohol">
<td align="right"><xsl:value-of select="@alkohol"/>%</td>
</xsl:if>
</tr>
</table>
</xsl:template>
</xsl:stylesheet>
Exercises
1. Browse through the collection of XML applications.
2. Add the recipe for tigerrejer to the XML recipe collection (save as file). Check that the result is well-formed XML.
3. Apply the given style sheet to this extended collection.
Add the necessary HTML to the following style sheet:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns="http://www.w3.org/1999/xhtml">
<xsl:template match="opskriftsamling">
<html>
<xsl:apply-templates select="opskrift"/>
</html>
</xsl:template>
<xsl:template match="opskrift">
<xsl:value-of select="titel"/>
<xsl:value-of select="energi/@kjoule"/>
<xsl:value-of select="energi/@fedt"/>
<xsl:value-of select="energi/@kulhydrat"/>
<xsl:value-of select="energi/@protein"/>
<xsl:if test="energi/@alkohol">
<xsl:value-of select="energi/@alkohol"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
which extracts nutrition tables from recipe collections. Try it out. As it stands, the output looks like:
<?xml version="1.0" encoding="ISO-8859-1"?>
<html xmlns="http://www.w3.org/1999/xhtml">
Smørrebrød med flødeost og tomat2616553411Citrontærte1510065314Græsk farsbrød og
agurkesalat13920463519Islagkage med
chokolade21655672742Laksemousse5838611722Nougattoppe8616692542Rabarberdessert med
jordbær852044542Hornfisk med radisesalat9140283834
</html>
No comments:
Post a Comment