XSL Processing Order - html

I've had trouble finding an exact, and simple, answer to this question on SO or elsewhere:
In XSL files, how can you tell which template will be processed first, second, etc? I read that it was ordered by how specific the XPath was. Additionally, is there a difference in XSL 1.0 vs. 2.0?
Finally, here is a flawed XSL file I am toying with. Currently the output is just the title "Table of Contents". I'll attach the XML here as well.
<xsl:template match="/">
<h1>
<xsl:text>Table of Contents</xsl:text>
</h1>
</xsl:template>
<xsl:template match="heading1">
<h2>
<xsl:value-of select="."/>
</h2>
</xsl:template>
<p>
<xsl:text>This document contains </xsl:text>
<xsl:value-of select="count(/article/body/heading1)"/>
<xsl:text> chapters. </xsl:text>
</p>
and the XML:
<article>
<title>
Creating output
</title>
<body>
<heading1>Generating text</heading1>
<heading1>Numbering things</heading1>
<heading1>Formatting numbers</heading1>
<heading1>Copying nodes from the input document to the output</heading1>
<heading1>Handling whitespace</heading1>
</body>
Any explanation as to why all the content isn't being displayed? Thank you for your help!

Here's what's happening:
The XSLT processor reads the root element of your XML
Then it looks in the stylesheet to see what matches. It finds your first template
It executes the first template.
The first template says to output the text, and then does nothing else, so the XSLT processor moves on to the next input element.... but you've processed the entire root node, so there are no more input nodes at the same level. It's done.
What you need to do is put an <xsl:apply-templates/> inside the first template. When this is encountered by the processor, it starts over but this time the context is the list of second-level nodes inside the root. It will look at each XML node in turn, find the best matching template in your stylesheet, and execute it.
This is a key concept -- The template is NOT in control, and is not procedural.

Related

XSLT: What is the best way to apply a floating text that will display the full expression for acronyms from an external dictionary file?

I'm new to XSLT.
I need to apply floating text that displays a setting for acronyms, as soon as the mouse cursor hovers over a word that is abbreviated.
My input file is XML, and every word that should display acronyms is represented in the following format:
<abbreviation Id="E.G."/>
When the mouse cursor hovers over the word EG, the floating text will be displayed: "for example".
I thought to apply the floating text using the HTML abbr tag
And the code I wrote is:
<xsl:template match="abbreviation">
<abbr title="for example.">
<xsl:value-of select="#Id"/>
</abbr>
</xsl:template>
I want the "title" attribute to be given as a parameter the definition of the main boxes from an external file that will contain a dictionary of related abbreviations and explanations.
I would love to know how to apply my issue.
And also get ideas about the external dictionary file - what kind of file should you create? For example, I would like a good structure of the file.
Note:
I use OXYGEN EDITOR,
And I believe I can also get solutions in XSLT version 2 and 3
Suppose your external dictionary looks like:
dict.xml
<dictionary>
<entry abbr="C.V.">course of life</entry>
<entry abbr="E.G.">for example</entry>
<entry abbr="N.B.">note well</entry>
</dictionary>
You can then use a key to transform an input like:
XML
<root>
<abbreviation Id="E.G."/>
</root>
using:
XSLT 2.0 (untested)
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="path-to-dictionary" select="'dict.xml'"/>
<xsl:key name="abbr-lookup" match="entry" use="#abbr" />
<xsl:template match="/root">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="abbreviation">
<abbr title="{key('abbr-lookup', #Id, document($path-to-dictionary))}">
<xsl:value-of select="#Id"/>
</abbr>
</xsl:template>
</xsl:stylesheet>
to get:
Result
<html>
<body>
<abbr title="for example">E.G.</abbr>
</body>
</html>
To understand the syntax used, read about Attribute Value Templates.
Well, XSLT does not float any text, it is a programming language to transform XML (or with XSLT 2 or 3, other input formats) to XML, (X)HTML, plain text. You seem to want to transform your XML to HTML in the hope the HTML user agent or browser displays a tooltip of the title attribute.
As for using an XML file as a secondary input file, if you have abbrvs.xml with
<root><abbr key="E.G.">for example.</abbr>...</root>
then in XSLT you can use
<abbr title="{key('abbr', #Id, doc('abbrvs.xml'))}">
<xsl:value-of select="#id"/>
</abbr>
to pull that title attribute value from the secondary input file if the XSLT declares a key
<xsl:key name="abbr" match="abbr" use="#key"/>

XML to XHTML transformation

I need to transform a XML to XHTML. Within the XML are multiple paragraphs and embedded quotations e.g.
<para>SomeText</para>
<para><quote>SomeText</quote></para>
<para>SomeText</para>
I tried this:
<xsl:choose>
<xsl:when test="//text/para">
<xsl:for-each select="//text">
<xsl:for-each select="//para">
<p><xsl:value-of select="text()"/></p>
</xsl:for-each>
</xsl:for-each>
</xsl:when>
<xsl:when test="//text/para[quote]">
<xsl:for-each select="//text">
<xsl:for-each select="//para/quote">
<p><q><xsl:value-of select="text()"/></q></p>
</xsl:for-each>
</xsl:for-each>
</xsl:when>
</xsl:choose>
The second condition simply gets ignored however.
As #LarsH indicates, avoid <xsl:for-each>. Use template matching.
This simple transformation:
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="para">
<p><xsl:apply-templates /></p>
</xsl:template>
<xsl:template match="quote">
<q><xsl:apply-templates /></q>
</xsl:template>
</xsl:transform>
will turn this:
<text>
<para>SomeText</para>
<para><quote>SomeText</quote></para>
<para>SomeText</para>
</text>
into
<p>SomeText</p>
<p><q>SomeText</q></p>
<p>SomeText</p>
Further reading here on SO:
What are the differences between 'call-template' and 'apply-templates' in XSL?
Why does XSLT output all text by default?
What is the default select of XSLT apply-templates?
The problem is you're using XPath expressions that ignore context (aside from the context document), i.e. expressions that start with //. So if you have any <para> element anywhere in the document that has a <quote> child element, the first condition will always be true and the second condition will never be reached.
Really you want to move the for-each loop (or probably better, a set of templates with match patterns and apply-templates) outside of the choose/when conditions. In fact you will probably not need a choose/when at all, once you have the right templates.
(Moving in some info from comments)
XSLT and XPath are sufficiently complex that it's really worth learning the basics before trying to get something working by trial-and-error. You'll save a lot of time that way. For a general introduction I would recommend
How XSLT Works
Then for more advanced discussion of xsl:for-each vs. xsl:apply-templates, see
Jeni Tennison's blog post Matching templates, named templates or for-each? My rules of thumb
differences between for-each and templates in xsl?

Styling inline XML tags with XSLT

This is a similar question to Style inline text along with nested tags with XSLT, but I can't comment to get clarification, so I will elaborate my specific scenario here. I basically have an XML document with the following structure:
<book>
<chapter>
<para>This is some text about <place>New York</place></para>
</chapter>
</book>
I am using XSLT to output XHTML from my XML file, and I want to be able to put span tags or something around the content in the place tag in the example above. The purpose is so that I can style these segments of text with CSS. Following the example I referenced above, I added this:
<xsl:template match="book/chapter/para/place">
<span class="place">
<xsl:apply-templates/>
</span>
</xsl:template>
When I load the XML document in the browser I get the error: "Error loading stylesheet: Parsing an XSLT stylesheet failed." (the stylesheet was loading properly before I added this part)
I'm assuming I lack some basic understanding of how xsl:apply-templates should be used. I would appreciate it if someone could point me in the direction of figuring this out.
Thanks!
The match:
<xsl:template match="book/chapter/para/">
applies templates to all children of the place element, rather than place itself.
Use select within apply-templates instead:
<xsl:template match="/">
<xsl:apply-templates select="book/chapter/para/place"/>
</xsl:template>
In the absence of a select attribute, the xsl:apply-templates instruction processes all of the children of the current node, including text nodes.
A select attribute can be used to process nodes selected by an expression instead of processing all children. The value of the select attribute is an expression. The expression must evaluate to a node-set.
References
XSLT 1.0 Specification

XSL applying tags incorrectly

I have a class project I'm working on but I've hit a point where I'm stuck and don't know what to do. My XSL (style6.xsl) works to an extent but it creates text instead of wrapping a chunk of my xml (Project6style.xml) so I have 2 sets of text but one isn't wrapped in any tags. I've spent all day trying to figure out why it's been doing this but I can't figure it out. I was hoping someone would be able to take a look at it.
If anyone could help it would be appreciated!
https://www.mediafire.com/?4b74nb1iltdqsqx
File Reference:
style6.xsl (what I need to edit so it looks a certain way)
Project6style.xml (what was given to me in the class project folder)
Tutorial.06 Project.doc (The assignment word document)
XSL Current Output.html (what my current xsl file is giving me)
XSL Output - WHAT IT SHOULD BE.html (What I'm assuming my professor wants it to look like)
Code for those who don't want to download:
XSL:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="4.0"/>
<xsl:template match="project">
<html>
<body>
<xsl:apply-templates/>
<h1>
<xsl:value-of select="student"/>
</h1>
<h2>
<xsl:value-of select="date"/>
</h2>
</body>
</html>
</xsl:template>
<xsl:template match="objective">
<xsl:apply-templates/>
<h4>
<xsl:value-of select=".//name"/>
</h4>
<div>
<xsl:value-of select="description"/>
</div>
</xsl:template>
</xsl:stylesheet>
XML:
<?xml version="1.0"?>
<!-- XML Project 6 -->
<?xml-stylesheet type="text/xsl" href="style6.xsl" ?>
<project>
<student>Student</student>
<date>Date</date>
<objective>
<name>Working with XSL</name>
<description>XSL is composed of three parts: XSL-FO
(Extensible Style sheet Language - Formatting Objects),
XSLT (Extensible Style sheet Language Transformations),
and XPath. XSL-FO is used to implement page layout and design.
XSLT is used to transform XML content into another presentation format.
XPath is used to locate information from an XML document
and perform operations and calculations upon that content.
</description>
</objective>
<objective>
<name>Introducing XSLT style sheets and processors</name>
<description>An XSLT style sheet contains instructions for transforming
the contents of an XML document into another format. An XSLT style
sheet document is itself an XML document, but has an extension .xsl.
An XSLT style sheet converts a source document of XML content into
a result document containing the markup codes and other instructions
for formatting.
</description>
</objective>
<objective>
<name>Creating an XSLT style sheet</name>
<description>To attach an XML file to the style sheet,
insert the processing instruction following the first line
in the document. An XSLT style sheet has the general structure
of all XML documents.
</description>
</objective>
</project>
HTML result (What my HTML file displays with these 2 files in their current state):
Student
Date
Working with XSL
XSL is composed of three parts: XSL-FO
(Extensible Style sheet Language - Formatting Objects),
XSLT (Extensible Style sheet Language Transformations),
and XPath. XSL-FO is used to implement page layout and design.
XSLT is used to transform XML content into another presentation format.
XPath is used to locate information from an XML document
and perform operations and calculations upon that content.
<h4>Working with XSL</h4><div>XSL is composed of three parts: XSL-FO
(Extensible Style sheet Language - Formatting Objects),
XSLT (Extensible Style sheet Language Transformations),
and XPath. XSL-FO is used to implement page layout and design.
XSLT is used to transform XML content into another presentation format.
XPath is used to locate information from an XML document
and perform operations and calculations upon that content.
</div>
Introducing XSLT style sheets and processors
An XSLT style sheet contains instructions for transforming
the contents of an XML document into another format. An XSLT style
sheet document is itself an XML document, but has an extension .xsl.
An XSLT style sheet converts a source document of XML content into
a result document containing the markup codes and other instructions
for formatting.
<h4>Introducing XSLT style sheets and processors</h4><div>An XSLT style sheet contains instructions for transforming
the contents of an XML document into another format. An XSLT style
sheet document is itself an XML document, but has an extension .xsl.
An XSLT style sheet converts a source document of XML content into
a result document containing the markup codes and other instructions
for formatting.
</div>
Creating an XSLT style sheet
To attach an XML file to the style sheet,
insert the processing instruction following the first line
in the document. An XSLT style sheet has the general structure
of all XML documents.
<h4>Creating an XSLT style sheet</h4><div>To attach an XML file to the style sheet,
insert the processing instruction following the first line
in the document. An XSLT style sheet has the general structure
of all XML documents.
</div>
<h1>Student</h1><h2>Date</h2>
This is one possible stylesheet, merely sticking to the structure of the input XML document:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="4.0" />
<xsl:template match="objective">
<h4><xsl:value-of select="name" /></h4>
<div><xsl:value-of select="description" /></div>
</xsl:template>
<xsl:template match="project">
<h1><xsl:value-of select="student" /></h1>
<h2><xsl:value-of select="date" /></h2>
<xsl:apply-templates select="objective" />
</xsl:template>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates select="project" />
</body>
</html>
</xsl:template>
</xsl:stylesheet>
note: I like to be specific about the target(s) of my apply-templates elements (hence the select="..." attribute), while some people prefer implicit selection; the choice is entirely up to you.

XSLT template matching issue

I am confused about XSLT apply-template statement. For example, here in w3school.
http://www.w3schools.com/xsl/xsl_apply_templates.asp
It is mentioned -- "The <xsl:apply-templates> element applies a template to the current element or to the current element's child nodes.", my question is whether it is applied to current element or to child nodes or both? The word "or" makes me confused about its definite behavior.
EDIT 1: here is the code snippet I am confused, I am confused when xslt processor finds <xsl:apply-templates/>, it will match all child nodes of "current node". Here "current node" means catalog or another virtual abstract XML root node? and why?
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
thanks in advance,
George
The w3schools documentation is not all it's cracked up to be, and I agree, it's quite misleading in this case.
The spec says:
In the absence of a select attribute, the xsl:apply-templates instruction processes all of the children of the current node, including text nodes.
"Children" in XML always means direct children. Children's children etc are called "descendents".
The "current node" means exactly that. It's determined by the context in which the apply-templates instruction appears.
So initially you might have:
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
Here the current node is the document node, and the apply-templates will act on the children to that, i.e. the top level element of the XML.
In this sample:
<xsl:template match="cd">
<xsl:apply-templates />
</xsl:template>
the current node will be a node somewhere in the XML called "cd" and the apply-templates will act on the direct children of that.
Note that this need not apply to every element called "cd", nor in fact need it apply to any element called "cd", that will depend on how the other templates in the XSLT process the input XML. All it says is that whenever that template is matched, the current node will be a "cd" node.
In case you want to apply templates to the current element, use:
<xsl:apply-templates select="."/>
<xsl:apply-templates/> matches all the child nodes of the current node.
In the e.g.
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
the current node (/) is catalog (root node). Hence will apply the templates that match all the child nodes (cd, title, artist, country, ...) if they exist.
Best way for you to understand would be to change the xslt in the example and observe the various outputs you get.
One way would be remove all the other 3 templates (cd, artist & title) and run the xslt again.
my question is whether it is applied
to current element or to child nodes
or both?
That depends on whether there is a select attribute in the apply-templates element.
If it's just <xsl:apply-templates/> then the template(s) that match the current element's child nodes will get applied. In the case from w3Schools this means that cd, title and artist all get applied.
However if you was to do something like <xsl:apply-templates select="/catalog/cd/artist"/> instead then only that element would get the template applied to it.