In this exercise, we work with an XML file originally coded by a Pitt student for a project on the Skyrim legends based on the video game. The XML code is available at http://newtfire.org/courses/tutorials/skyrim.xml. You should right-click on this link, download the file, and open it in <oXygen/>. (You don’t need the Relax NG schema, but if you’d like to look at it and associate it with the file, it’s available at https://newtfire.org/courses/tutorials/skyrim.rnc).
Because this document is not in a namespace, we do not need the
@xpath-default-namespace
attribute, and the only thing we need to add
to <oXygen>’s default XSLT stylesheet template is the @xmlns
attribute pointing to the HTML namespace. We also add our usual
<xsl:output>
line that we use when producing HTML (for making
sure we produce valid HTML 5 in XHTML format). Here’s what we need:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:math="http://www.w3.org/2005/xpath-functions/math" exclude-result-prefixes="xs math" xmlns="http://www.w3.org/1999/xhtml" version="3.0"> <xsl:output method="xhtml" encoding="utf-8" doctype-system="about:legacy-compat" omit-xml-declaration="yes"/>
We will be preparing HTML reading view styled for the web, based on the original XML document. We’re going to work with the <body>
element,
concentrating on processing the in-line elements to style the text. You can use some of
the basic HTML in-line elements, like <em>
for emphasis or
<strong>
for strong emphasis, but you’ll also want to use CSS to
set some elements to different colors or background colors or borders or fonts or font
sizes or font styles (e.g., italic) or font weights (e.g., bold) or text decoration
(e.g., underlining) or text transformation (e.g., convert to all upper case) … well …
anything else. We describe below how to do that.
There are six types of in-line elements in the input XML document:
<QuestEvent>
<QuestItem>
<character>
<epithet>
<faction>
<location>
Some are immediately inside a <paragraph>
and some are inside other
elements that are inside paragraphs. You may not know at the outset which ones can be
inside which other ones, or how deeply they can nest. Happily, with XSLT, unlike with
many other programming languages, you don’t need to care about those questions!
Prose paragraphs with in-line elements that might contain other in-line elements are
richly mixed content, with varied and unpredictable combinations of elements and plain
text. This is the problem that XSLT was designed to solve. With a traditional procedural
programming language, you’d have to write rules like inside this paragraph, if
there’s a
That is, most programming languages
have to tell you what to look for at every step. The elegance of XSLT when dealing with
this type of data is that all you have to say inside paragraphs and other elements is,
<QuestEvent>
do X, and, oh, by the way, check whether
there’s a <QuestItem>
or a <location>
inside
the <QuestEvent>
, etc.I’m not worried about what I'll find here; just process (apply templates to) all
my children, whatever they might be.
The way to deal with mixed content in XSLT is to have a template rule for every element
and use it to output whatever HTML markup you want for that element and then, inside
that markup, to include a general <xsl:apply-templates/>
, not
specifying a @select
attribute. For example, if you want your
<QuestEvent>
to be tagged with the HTML
<strong>
tags, which means strong emphasis
and which is
usually rendered in bold, you could have a template rule like:
<xsl:template match="QuestEvent"> <strong> <xsl:apply-templates/> </strong> </xsl:template>
You don’t know or care whether <QuestEvent>
has any child nodes or, if
it does, what they are. Whatever they are, this rule tells the system to try to process
them, and as long as there’s a template rule for them, they’ll get taken care of
properly somewhere else in the stylesheet. If there are no child nodes, the
<xsl:apply-templates/>
will apply harmlessly (as there will be nothing to process). As
long as every element tells you to process its children, you’ll work your way down
through the hierarchy of the paragraph without having to know which elements can contain
which other elements or text nodes.
@select
In the previous XSLT assignment, where you built HTML tables from XML-coded survey data,
you used <xsl:apply-templates select="…"/>
, specifying exactly what
you wanted to process where. That makes sense when your input (those <fs>
and <f>
elements and their special attributes) and your output (an
HTML table) are very regular in structure. Use the @select
attribute
when you know exactly what you’re looking for and where you want to put it.
In this assignment, on the other hand, you don’t know (and don’t need to know) the order
and nesting hierarchy of whatever tossed salad
of elements and plain text you might find inside
a paragraph or its subelements. You just want to process whatever comes up whenever it
comes up. <xsl:apply-templates/>
without the @select
attribute says apply templates to whatever you find.
The upshot: Omit the @select
attribute when you are processing lots of different mixed up alternatives and you do not need to rearrange them. (You can still treat them all
differently because you’ll have different template rules to match
them, but when
you assert that they should be processed, you don’t have to know which ones they actually
are.)
HTML provides a limited number of elements for styling in-line text, which you can read
about at http://www.w3schools.com/html/html_formatting.asp. You can use any of these in
your output, but note that presentational elements, the kind that describe how text
looks (e.g., <i>
for italic
), are generally regarded as less
useful than descriptive tags, which describe what text means (e.g.,
<em>
for emphasis
). Both of the preceding are normally
rendered in italics in the browser, but the semantic tag is more consistent with the
spirit of XML than the presentational one.
The web would be a dull world if the only styling available were the handful of presentational tags available in vanilla HTML. In addition to those options, there are also ways to assign arbitrary style to a snippet of in-line text, changing fonts or colors or other features in mid-stream. To do that:
Before you read any further in this page, read our Using
<span>
and @class
to style your HTML
page.
To use the strategies described at that page, create an XSLT template rule that
transforms the element you want to style to an HTML <span>
element with a @class
attribute. For example, you might transform
<faction ref="MythicDawn">assassins</faction>
in
the input XML to <span
class="MythicDawn">assassins</span>
in the output HTML. You
can then specify CSS styling by reference to the @class
attribute,
as described in the page we link to above.
<faction>
elements to the same
HTML @class
, you can create separate template rules to match on
factions according to their attribute values. For example,
<xsl:template match="faction[@ref='MythicDawn']">
is
a normal XPath expression to match <faction>
elements
only if they have a @ref
attribute with the value
MythicDawn.
@alignment
attribute) as
evil,
good, or
neutral. You can write a matching rule that will dereference the
@ref
attribute on,
say, <faction ref="MythicDawn">assassins</faction>
,
look up whether this is an evil, good, or neutral faction, and set the
@class
value accordingly. You could make all good factions
one color and all evil factions a different color, letting XPath look up the
moral alignment of a faction for you.Setting the @class
attributes in the output HTML makes it possible
to style the various <span>
elements differently according to
the value of those attributes, but you need to create a CSS stylesheet to do
that. Create the stylesheet (just as you‘ve created CSS in the past), and
specify how you want to style your <span>
elements. Link the
CSS stylesheet to the HTML you are outputting by creating the appropriate
<link>
element in your output HTML (you can remind
yourself how to do that here in this section of our Intro to
CSS). You should set that <link>
element in your XSLT so it is always output every time you update your code.
What you should produce, then, is:
<body>
element and its
contents into HTML.<span>
elements
with the @class
attribute.CSS stylingfor styling backgrounds, text, and fonts, as well as the link for borders under
CSS box model.
Please upload your XSLT, HTML, and CSS files to Canvas. Remember to link your CSS to the HTML file!