Adding a 'title=' attribute.
I want to be able to add optional titles to both the
<section> and
<code>
tags. In other words, I should be able to add a title like this:
Desired usage of 'title' attribute
<section title="A section title">
<code title="A code title">
To do this requires the use of conditional operations in the XSLT file.
They are a bit hard to read at first, but are easy to use for simple things,
once you see the pattern.
First, lets rewrite the
<code> template to add an optional title.
For reference, here
is the current version:
Current <code> container
<!-- <code> container -->
<xsl:template match="code">
<div class="code">
<!-- ugh - substring() hack is to remove leading \n at start
of code block. Without this hack, it looks okay when
run through xsltproc, but has a gap when viewing the XML
directly in Firefox.
-->
<pre><xsl:value-of select="substring(.,2)" /></pre></div>
</xsl:template>
I'm going to restructure this a bit. Since we'll now be creating two
items (a title and the content itself) it makes sense to place these
into a parent container. That way, the positioning of the code box relative
to surrounding content remains the same, regardless of whether a title
is present. If the title and content were standalone
div containers,
it would be harder to get the spacing correct.
The new <code> template, with a title
<!-- <code> container -->
<xsl:template match="code">
<!-- Put title+content in a parent container -->
<div class="code-container">
<!-- Add title, if user provided one -->
<xsl:if test="string-length(@title)">
<div class="code-title">
<xsl:value-of select="@title" />
</div>
</xsl:if>
<!-- Include code as preformatted block -->
<div class="code-content">
<!-- ugh - substring() hack is to remove leading \n at start
of code block. Without this hack, it looks okay when
run through xsltproc, but has a gap when viewing the XML
directly in Firefox.
-->
<pre><xsl:value-of select="substring(.,2)" /></pre></div>
</div>
</xsl:template>
The
<xsl:if test="string-length(@title)"> is to make sure I only
add a
<div> for the title if one was given. Although an empty
<div> should be invisible under a user's browser, I think it is better
to avoid any problems and not create the empty
<div> to begin with.
Now we have to define the styles for these three
<div> containers.
Note that these
replace the
div.code style that is currently defined:
Styles for the three code <div> containers
/*
<code> creates 3 divs:
code-container: Overall container.
code-title: Title (optional).
code-content: The code itself.
*/
div.code-container {
font-size: 1em;
margin-left: 1em;
background: #bbbb00;
margin-top: 1em;
margin-bottom: 1em;
}
/* The title for the code box */
div.code-title {
background: #555555;
color: #ffff00;
font-size: .9em;
padding-left: .8em;
padding-right: .8em;
padding-top: 0.2em;
padding-bottom: 0.2em;
border: 1px solid black;
}
/* The code itself */
div.code-content {
background: #dddddd;
padding-left: .8em;
padding-right: .8em;
border: 1px solid black;
/* hide any text that falls outside the bounding box */
overflow: hidden;
}
Similarly, a title attribute is added to the
<section> tag.
Note that the logic is a bit different here: If no title is given,
I still want to add a blank title so that the styling will be picked
up and displayed. (In particular, I want the horizontal border to show
up, even if no title is given.)
Adding a <section> title.
<!-- The <section> tag -->
<xsl:template match="section">
<div class="section">
<xsl:choose>
<!-- Use title=, if given -->
<xsl:when test="string-length(@title)">
<div class="section-title"><xsl:value-of select="@title"/></div>
</xsl:when>
<xsl:otherwise>
<!-- If no title, make empty title so I still get the border -->
<div class="section-title"></div>
</xsl:otherwise>
</xsl:choose>
<xsl:apply-templates />
</div>
</xsl:template>
This template defines one new
<div> class:
div.section-title.
Let's add a style for it:
Adding a style for the section title
/* the section title */
div.section-title {
font-size: 1.2em;
font-weight: bold;
padding-bottom: 0.2em;
border-bottom: 1px solid black;
margin-bottom: 1em;
}