boodebr.org
MYOML: Metainfo, notes, warnings, and more HTML tags
This time I'm going to restructure the root template to add metainfo to the article. The metainfo is used to create the overall page layout, but can also be useful in if I ever want to create an article index. A script will be able to easily pull the metainfo from the article to create a database, etc.

I'm also going to add some 'note' and 'warning' boxes for highlighting important details, and add a few more HTML tags.
More HTML tags
I want to be able to use lists in my XML documents, just like HTML. No need to invent new tags for this, I'll just add the <ul>, <ol>, and <li> tags to my template. To do this, I just expanded the set of matched tags I already had in the "copy" template:
Adding even more HTML tags ...
<!-- Pass along the <p>, <i>, <b>, <tt>, <ul>, <ol>, <li> tags -->
<xsl:template match="p|i|b|tt|ul|ol|li">
    <xsl:copy>
        <xsl:apply-templates />
    </xsl:copy>
</xsl:template>
I also want to add the <a> tag. At first glance, it seems like I should be able to just add it to the "or" list in the template above. However, there is a problem: The XSLT specification states that node attributes are not automatically copied, so the "href" attribute would be stripped from the <a> tag. Obviously this will not work. There is a way to automatically copy the attributes (using the 'use-attribute-sets' parameter to <xsl:copy>), but Firefox seems to have a bug in its XSLT processor, so I do it manually.
Adding the <a> tag
<xsl:template match="a">
    <a>
        <xsl:attribute name="href">
            <xsl:value-of select="@href" />
        </xsl:attribute>
        
        <xsl:apply-templates />
    </a>
</xsl:template>
Note the use of <xsl:attribute> above. This is used to add attributes to the currently opened tag (<a>, in this case). You might be tempted to try and implement the <a> tag this way:
NOT the way to add an attribute ...
<a href='<xsl:value-of select="@href"'> ... </a>
But you'll find that this doesn't work. You have to use the <xsl:attribute> function in these situations.
Article metainfo
Up until now, the overall document structure has been created by the template matching the root ("/") element:
Current root template
<xsl:template match="/">
    <html>
        <head>        
            <link href="style.css" rel="stylesheet" type="text/css" />
        </head>
        <body>
            <xsl:apply-templates />
        </body>
    </html>
</xsl:template>
I'm going to change this now and have the <article> template create the header. There are two reasons for this:
  1. Philosophical: <article>, not "/", is the true content root, so matching should really start there.
  2. Technical: I want to add meta info in the <head> section. Since this meta info will be attached to the <article> tag, the <head> section needs to be created by the <article> template.
Here is an example of the metainfo I want to add to the <article> tag:
Article metainfo
<!-- Article meta information:
        title = Title of this article.
        series = Name of the overall series.
        series-url = URL for series index.
        footer-text = Lead-in text for series URL at bottom
        series-url-desc = Descriptive text for series URL <a> -->
<article 
    title="A Sample Article"    
    series="MYOML"
    series-url="http://boodebr.org/series/myoml"    
    footer-text="Looking for the series index?"    
    series-url-desc="The main MYOML page"
    >

Here is the new <article> template. It combines the root template with the previous <article> template, and adds the metainfo described above:
New <article> template
<!-- The <article> tag -->
<xsl:template match="article">
    <html>
        <head>        
            <link href="style.css" rel="stylesheet" type="text/css" />
            <!-- Put article title in <title> element as well -->
            <title><xsl:value-of select="@series" />: <xsl:value-of select="@title" /></title>            
        </head>

        <body>
            <div class="article-container">
                <!-- Show a standard header -->
                <div class="article-header">
                    <a class="hide">
                        <xsl:attribute name="href">
                            <xsl:value-of select="@series-url" />
                        </xsl:attribute>                
                        <xsl:value-of select="@series" />
                    </a>: <xsl:value-of select="@title" />                    
                </div>
                
                <!-- Apply templates to article content -->
                <xsl:apply-templates />
                
                <!-- Show a standard footer -->
                <div class="footer">
                    <xsl:value-of select="@footer-text" />
                    &#160;
                    <a>
                        <xsl:attribute name="href">
                            <xsl:value-of select="@series-url" />
                        </xsl:attribute>                
                        <xsl:value-of select="@series-url-desc" />
                    </a>
                </div>        
            </div>
            
        </body>
    </html>
</xsl:template>
Note that it uses the <xsl:attribute> function just like the <a> tag template does.

To briefly note: I'm using two classes of links in this template - 'normal' and 'hidden'. I'm using 'hidden' links in cases like the series title, where I want the viewer to be able to click it, but not have it stand out. In other words, its not so much to hide that there is a link, but just to not make it look ugly. I use 'normal' links in places where I want to call the viewer's attention to the link.

The 'normal' style will be used for all <a> tags that don't specify a class:
Normal link style
a:link {
    text-decoration: underline;
    color: #0000ff;
}

a:hover {
    color: black;
    background: #ffff00;
}

a:visited {
    text-decoration: underline;
    color: #000088;
}
And here is the style for tags written as <a class="hide" >...</a>:
Hidden link style
a.hide:link {
    text-decoration: none;
    color: black;
}

a.hide:hover {
    color: black;
    background: #ffff00;
}

a.hide:visited {
    text-decoration: none;
    color: black;
}
Notes and Warnings
Here and there I find I want to highlight some particular bit of text for the reader, either informational ("notes") or cautionary ("warnings") in nature. I'm going to add the tags <note> and <warn> for these situations:
Note template
<!-- <note> container -->
<xsl:template match="note">
    <div class="note-container">
        <div class="note-title">    
        <!-- use title= if user gave it, else use "NOTE" -->
        <xsl:choose>
            <xsl:when test="string-length(@title)">
                <xsl:value-of select="@title" />
            </xsl:when>
            <xsl:otherwise>NOTE</xsl:otherwise>
        </xsl:choose>
        </div>
        
        <div class="note-content">
            <xsl:apply-templates />    
        </div>
        
    </div>

</xsl:template>
And one for warnings:
Warning template
<!-- <warn> container -->
<xsl:template match="warn">
    <div class="warn-container">
        <div class="warn-title">    
        <!-- use title= if user gave it, else use "WARNING" -->
        <xsl:choose>
            <xsl:when test="string-length(@title)">
                <xsl:value-of select="@title" />
            </xsl:when>
            <xsl:otherwise>WARNING</xsl:otherwise>
        </xsl:choose>
        </div>
        
        <div class="warn-content">
            <xsl:apply-templates />    
        </div>
        
    </div>

</xsl:template>
I used the same logic here as with the <code> template and created a parent container to hold the title+content entities. In this case, there will always be a title, so it isn't as urgent to have a parent container, but in a structural sense, it is good to group related items together.

Here are the new styles for these boxes:
Note and warning styles
div.note-container {
    margin-left: 1em;
    margin-right: 1em;
    margin-top: 1em;
    margin-bottom: 1em
}

div.note-title {
    font-size: 1em;
    text-align: center;
    font-weight: bold;
    border: 1px solid #000000;
    background: #59a2a3;
    color: #ffffff;
    padding-top: 3px;
    padding-bottom: 3px;    
}

div.note-content {
    font-size: 1em;
    border: 1px solid #888888;
    background: #e3efef;
    color: #000000;
    padding-left: 1em;
    padding-right: 1em;
    padding-top: 0.8em;
    padding-bottom: 0.8em;
}

div.warn-container {
    margin-left: 1em;
    margin-right: 1em;
    margin-top: 1em;
    margin-bottom: 1em
}

div.warn-title {
    font-size: 1em;
    text-align: center;
    font-weight: bold;
    border: 1px solid #000000;
    background: #ff0000;
    color: #ffffff;
    padding-top: 3px;
    padding-bottom: 3px;    
}

div.warn-content {
    font-size: 1em;
    border: 1px solid #888888;
    background: #eeeead;
    color: #000000;
    padding-left: 1em;
    padding-right: 1em;
    padding-top: 0.8em;
    padding-bottom: 0.8em;
}
Sample article
I just built on top of the previous sample article for this one. The parts I added were the metainfo at the top:
Added at top ...
<article 
    title="A Sample Article"    
    series="Testing it Out"
    series-url="http://boodebr.org/series/myoml"    
    footer-text="Looking for the series index?"    
    series-url-desc="The main MYOML page"
    >
And a new section to demonstrate the new <note> and <warn> boxes, and the extra HTML tags:
Added at bottom ...
    <section title="Section 3 - Other HTML tags">
        <text>
            Here is a link to <a href="http://www.python.org">python.org</a>
            <p/>
            Here is a list of fruits, unordered:
            <ul>
            <li>Apple</li>
            <li>Orange</li>
            <li>Banana</li>
            </ul>
            And as an ordered list:
            <ol>
            <li>Apple</li>
            <li>Orange</li>
            <li>Banana</li>
            </ol>

            Here is a note box:
            
            <note title="Important Note">
            Here is an important note about nothing. Here is some more text
            to fill the box up and make it wordwrap.
            <p/>
            Here is a second paragraph in the box.                
            </note>

            And now a warning box:
            
            <warn>
            Here is an important warning about nothing. Here is some more text
            to fill the box up and make it wordwrap.
            <p/>
            Here is a second paragraph in the box.                
            </warn>
            
        </text>
    </section>
Results
You can see the final article here: article.xml

As before, if you need to run the XSLT transformation yourself, here are the pieces:
  1. template.xsl
  2. style.css