|
home—lects—hws
D2L—breeze (snow day)
Originally based on XML Visual Quickstart Guide by Kevin Howard Goldberg, and notes therefrom by Jack Davis (jcdavis@radford.edu).
The next step in learning to use XML is understanding how to format these documents. The details for formatting XML documents was originally in a specification called XSLT, which stands for eXtensible Style Language Transformations. Chapters 2-4 explain how to use XSL to transform XML documents. The end result might be another XML document, or an HTML document (most common). You can transform an XML document into practically any document type.
Transforming an XML document means taking in one XML tree and producing another — a function from XML trees to XML trees. For example, consider the input
<my_children> <child> <name>Logan</name> <gender>M</gender> <age>7</age> </child> <child> <name>Rebecca</name> <gender>F</gender> <age>3</age> </child> <child> <name>Lee</name> <gender>F</gender> <age>2</age> </child> </my_children>An XSLT program might take this and return a new XML tree:
<html> <body> <h3>Some Kids</h3> <ul> <li>Logan, who is 7</li> <li>Rebecca, who is 3</li> <li>Lee, who is 2</li> </ul> </body> </html>
Rather than write such a function in Java or a general-purpose programming language, XSLT is a domain-specific language, specifically invented to make these tree-transformations easy to write. XSLT can be used to reorder the ouput according to user established criteria, display only portions of the document, and more.
Examples of data stored as XML:
<xsl:for-each select="nodeSpec"> results... </xsl:for-each> |
<?xml-stylesheet type="text/xsl" href="foo.xsl"?> |
Once the browser has constructed the XML data tree, it then transforms that XML tree using the XSLT instructions, yeilding a new tree. The transformation rules are called “templates”; they correspond to functions in a programming language — a function which is given an XML node as input, and returns a (new) XML node.
(Note: usually the output happens to be XHTML, but it can in theory be any XML.)
A particular transformation (“template”)
looks at one node of the input tree [including its subtree],
and produces a (sub)tree to include in the overall output.
In the my_children example above,
there might be one “helper” XSLT template which,
given a
In our context, it's the browser which invokes the XSLT processor, and the result is html. (The XSLT is being run client-side.) However, that's not required — XSLT can produce any XML output, and the XSLT processing can be run stand-alone.
<?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> |
</xsl:stylesheet> |
<xsl:template match="/" > <!-- rule for root-element here --> </xsl:template> |
Note:If you do not include a root template in the XSLT stylesheet, a root template built in to XSLT will be used (typically not what you want).
After running the XSLT program, we have newly-built XML tree;
the very last step is to flatten that tree back to a string
and print it as output.
We can use the
In 95% of all cases, our resulting XML tree is HTML, and so we'll include
<xsl:output method="html"/> |
Note that
Example:
Putting the above together, we'll make a trivial XSLT program
which ignores its input entirely, always generating the same, constant output page:
constant.xml
constant.xsl
The body of the loop is XSLT,
where the implicit-root of any relative XPATHS is
one of the things selected by the
Note how the syntax of
<p> This person is <xsl:choose> <xsl:when test="height > 200"> extremely </xsl:when> <xsl:when test="height != 0"> <xsl:value-of select="height"/> cm </xsl:when> <xsl:otherwise> unknown </xsl:otherwise> </xsl:choose> tall. </p> |
<xsl:if test="boolean expression"> <!-- other XSLT statements statements --> </xsl:if> |
<xsl:if test="name[@language='English']"> It's called <xsl:value-of select='name'>. </xsl:if> |
observation: Placing thexsl:sort tag as the first-child inside the loop's body is definitely odd. It would be more natural to have a stand-alonesort tag which takes the XPATH of the nodes to sort, and returns a “list” of the sorted nodes. Or, the loop's control-flow should all be set via attributes. Alas, they didn't ask me when designing it. (There is actually a vague scoping reason for their design choice: there are XPATH issues since thexsl:for-each is working on the parent node, but the sort'sselect expression is relative to a child. In most langauges this is solved viasort being passed a function, and that function knows it will handle the individual-element type.)
<xsl:attribute name="att_name"> <!-- Here, specify the value of the new attribute. Of course, you can use any XML: literal, or and XSLT instructions. This body gets spliced into the enclosing tag (!) --> </xsl:attribute> |
Suppose we want each Wonder to be a link —
that is instead of the plain text “
<a> <xsl:attribute name="href"> #<xsl:value-of select="name" /> <!-- link-target --> </xsl:attribute> <xsl:value-of select="name" /> <!-- link-text --> |
(Like
Note: Thexsl:attribute tag must be the first child within the tag you're trying to effect. If we swapped thexsl:value-of andxsl:attribute nodes within thea , nothing renders at all. (There is no deep conceptual reason for this restriction.)
In the above example, note that although the code happens to work, it is not actually valid:
the value of the
An xslt short-cut: curly-braces
In XSLT, curly-brackets are interpreted as an xpath expression.
This provides a quick-and-dirty way to avoid
This shortcut
that works particularly well when generating attributes:
rather than requiring
Note: We will not emphasize this feature, in this course. Even though abstracting-into-a-function is one of the most fundamental aspects of programming, it's a bit unwieldy (and non-intuitive, and therefore not-particularly-common) to do so in XSLT. (Besides, our interest in XSLT is more as a vehicle to introduce the domain-specific languages xpath and DTDs, rather than than the language XSLT itself.)
The root template is the first thing processed in an XSLT style sheet. XSLT allows you to create more templates than just the root template. This allows you to create different sets of processing rules to apply to different parts of the XML document.
One of the main benefits of using templates is the ability to reuse a template for other nodes in your document. In the same way that one can use functions in most programming languages, you would create a template, and simply apply that template whenever necessary. This eliminates the need to repeat the same processing instructions.
In our ongoing example: We have been putting the non-english name in parentheses and italics. Suppose we want to do that throughout, consistently, and make it easy to maintain any changes or tweaks to this decision. We can define a template to process non-English name nodes, and then apply it in different contexts. (E.g. if there are tags for “newspaper”, we could apply the same template for non-English names there.)
<!-- Define the function --> <xsl:template match="name[@language!='English']"> (<em><xsl:value-of select="."/></em>) </xsl:template> |
The system looks for and calls the template for "/" automatically;
other templates are only invoked via
There is a default template that gets called, if one doesn't otherwise apply:
For a text node, just return the text;
for a tag node, recursively call
You can't provide other arguments to templates — just the xpath of the element to process. And you can't call templates on any ol' node — you must specify (when you create the template) what xpaths it applies to.
<xsl:apply-templates select="ancient_wonders/wonder"> <xsl:sort select="height" order="descending" data-type="number" /> </xsl:apply-templates> |
Similar to how a web-page (data) can have a css-stylesheet directive (processing), XML data files have a xml-stylesheet tag, with what XSLT file processes them.
It's annoying, that the
// The file children.php: <?xml-stylesheet type="text/xsl" href="children.xsl"?> <?php require('children-data.xml'); ?> |
1Don't try editing the file w/o make a copy of the file and probably the .itl (real library file) as well. ↩
2 Remember, one of the XML requirements is that there is exactly one top-level tag. ↩
3
The reason for the lack of
4
Perhaps they should use an English term beside “if”;
perhaps
5
In php it's no problem to have an expression whose result
was inserted into the middle of an attribute.
However, since XSLT is itself written in XML,
and XML of course doesn't allow opening a tag in the middle of an attribute,
the syntax physically precludes putting
home—lects—hws
D2L—breeze (snow day)
©2014, Ian Barland, Radford University Last modified 2014.Nov.21 (Fri) |
Please mail any suggestions (incl. typos, broken links) to ibarlandradford.edu |