<xsl:element>
Up to now, when we have wanted to include an element in the
result tree, we have just gone ahead and typed the start and end tags into the
stylesheet. In most cases, that works. However, it will not work if the element
name depends on data in the source XML document.
In this case we use <xsl:element> to create the element for us. This is used most
frequently when creating an element-rich result tree from an attribute-rich
source tree. However, we don't have an attribute-rich document to play with, so
we will simply create element names based on the id attributes of the books in our catalog. We cannot
use the id values themselves as element names. (Why not? Think
back to your XML specification or wait to see at the end of this section.) So
we will use the following code (id.xsl):
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template
match="/">
<xsl:apply-templates
select="Catalog/Book"/>
</xsl:template>
<xsl:template
match="Book">
<xsl:element
name="id{@id}"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
Notice the line:
<xsl:element name="id{@id}"/>
The part in braces is an attribute value
template, a feature of
XSLT we will be meeting in the next chapter. This is the required format for
the value of the name attribute.
Notice also the use of <xsl:text>:
The purpose of this was to put a line break between each
element of the output. This is only there to make
the resulting serialized document more readable. And here it is (when applied
to catalog.xml):
<?xml version="1.0"
encoding="utf-8"?>
<id1861003323/>
<id1861003129/>
<id1861003110/>
<id1861003412/>
<id1861004028/>
<id1861001576/>
<id1861004044/>
<id1861004583/>
<id186100303X/>
<id1861003021/>
<id1861003439/>
<id1861002858/>
<id1861002289/>
<id1861001525/>
There is another occasion you might want to use <xsl:element>.
Because the element allows a namespace
attribute, it provides more
control over the namespace than we have when including the element as literal
text in the stylesheet. Just as we have made the element name in the result
tree dependent on the content of the input tree, we can do the same with a
namespace. Like the name attribute, the value of this attribute is an
attribute value template.
The final, optional, attribute of <xsl:element>,
called use-attribute-sets,
allows us to specify an attribute set to use with the defined element. Such
sets of attributes can be defined using the <xsl:attribute-set>
element.
Why couldn't we use the id
values themselves as element names
earlier? Our id
values start with a digit remember from the XML specification that an element
name must start with an alphabetic character or an underscore or colon. Of
course, we would never use a colon as this is used as a separator between a
namespace prefix and local name.
<xsl:attribute>
You will probably find that you use <xsl:attribute>
more often than <xsl:element>, particularly if you are creating
HTML output.
This element allows us to create an attribute name and/or
value in the result tree based on data in the source tree. For example, in our
book catalog we have references to images of the book covers, such as:
<CoverImage>3323.gif</CoverImage>
If we were to display information from the catalog by creating
an HTML page, we would want to create an <IMG>
element referring to this
image. Something like:
<IMG src="covers/3323.gif">
We can do this using an attribute value template. The
following stylesheet, covers.xsl, creates a table of book titles and images:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<xsl:apply-templates select="Catalog"/>
</xsl:template>
<xsl:template match="Catalog">
<TABLE><xsl:apply-templates
select="Book"/></TABLE>
</xsl:template>
<xsl:template match="Book">
<TR>
<TD><xsl:value-of select="Title"/></TD>
<TD>
<IMG>
<xsl:attribute name="src">
covers/<xsl:value-of select="CoverImage"/>
</xsl:attribute>
</IMG>
</TD>
</TR>
</xsl:template>
</xsl:stylesheet>
Note that we have used the line:
<xsl:output method="html"/>
This ensures that the resulting <IMG>
element does not use the empty element syntax. The serialized output will
have an element of the form:
<IMG src="covers/4583.gif">
rather than:
<IMG src="covers/4583.gif"/>
This ensures compatibility with a greater range of older
browsers.
The part we are most interested in is:
<IMG>
<xsl:attribute
name="src">
covers/<xsl:value-of
select="CoverImage"/>
</xsl:attribute>
</IMG>
Note that normally I would
put the <xsl:attribute> element and all its content on a single line. This is because this
element contains a text node (covers/), and so the additional whitespace will be
included in the output. I have only reformatted this line to make it fit within
the constraints of the printed page.
All the code above is doing is creating the <IMG>
element in the output with a src
attribute using the value of the
text node of the <CoverImage> element in the source tree. In this
case, we have included some additional text to provide the correct relative URL
for the images.
This screenshot shows the first four books:
Note that you would not
use both an <xsl:attribute>
and an <xsl:element>
element. Instead you would use an attribute value template.
We have now covered the main elements of XSLT. With these,
you can write many useful stylesheets. We will next look at two important
aspects of XSLT default templates and what happens when several templates
match the same pattern.