boodebr.org
MYOML: Adding the final few tags
The article-markup language is almost complete, just a few more nice-to-have blocks to add this time around:
  • Images
  • "Inner" code blocks
  • Tables
Images
I'm going to reuse the familiar <img> tag from HTML, but add a title attribute to give a label for the image. The syntax will be:
The <img> tag
<img src="..." title="A title" />
The title is optional. Here is the XSLT template to add the image tag:
<img> tag template
<!-- images - by default, I want to center them horizontally -->
<xsl:template match="img">
    <!-- Trick for centering images by placing them in a container.
         From: http://www.netmechanic.com/news/vol7/html_no10.htm -->
    <div class="image-container">
        <img>
            <xsl:attribute name="src"><xsl:value-of select="@src" />
            </xsl:attribute>
        </img>
        <!-- add title= if one is given -->
        <xsl:if test="string-length(@title)">
            <div class="image-title">
                <xsl:value-of select="@title" />
            </div>
        </xsl:if>       
    </div>    
</xsl:template>
Here are the corresponding styles for the new blocks:
Image styling
div.image-container {
    margin-top: 1em;
    margin-bottom: 1em;
    padding: 0;
    text-align: center;
}

div.image-title {
    font-weight: bold;
}
"Inner" code blocks
If you try to place a <code> block inside of a <note> or <warn> tag, it will work fine, but the formatting doesn't look quite correct. What I really want to do is apply a different template in this situation.

To match a code block inside of a note or warn tag, all that you have to do it match it like this:
Matching an inner code block
<xsl:template match="note//code|warn//code">
The | symbol means "or" - it matches either note//code or warn//code. The // means to match a code tag anywhere underneath a note or warn tag. If you said warn/code, then it would only match a code tag immediately underneath a warn tag, but no deeper.

Here is the template for the "inner" code block:
Inner code template
<!-- <code> container inside of a <warn> or <note> gets 
     different styling to make it look better in those containers -->
<xsl:template match="warn//code|note//code">

    <!-- Put title+content in a parent container -->
    <div class="inner-code-container">
        <!-- Add title, if user provided one -->
        <xsl:if test="string-length(@title)">
            <div class="inner-code-title">
                <xsl:value-of select="@title" />
            </div>
        </xsl:if>       

        <!-- Include code as preformatted block -->
        <div class="inner-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>
Here are the corresponding styles for the inner code block:
Styles for inner code blocks
/* 
    This is for <code> tags inside either a <warn> or <note> container.
    
    Just like the normal <code>, this creates 3 divs:
    
        inner-code-container: Overall container.
        inner-code-title: Title (optional).
        inner-code-content: The code itself.
*/
div.inner-code-container {
    font-size: 1em;
    margin-left: 1em;
    margin-right: 1em;
    background: #bbbb00;
    margin-top: 1em;
    margin-bottom: 1em;
}

/* The title for the code box */
div.inner-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 dashed black;
}

/* The code itself */
div.inner-code-content {
    background: #dddddd;
    
    padding-left: .8em;
    padding-right: .8em;

    border: 1px dashed black;
    
    /* hide any text that falls outside the bounding box */
    overflow: hidden;    
}
Tables
For the time being, I'm going to add simple (HTML-style) tables. These will use the standard <table>, <tr>, <th>, and <td> tags. The only change will be that a title= attribute is added to the <table> tag to give the table a caption. Note that I use a separate <div> for the table caption, instead of relying on the HTML <CAPTION> tag. I do it this way to make sure I can precisely control the placement of the caption. It's mainly a matter of taste - if you prefer the <CAPTION> tag, then by all means, use it.

Here is the table template:
The <table> template
<!-- Basically the same as an HTML table, but the title is
     given as the title= attribute -->
<xsl:template match="table">
    <!-- Place inside outer container, as done with <code>, etc. -->
    <div class="table-container">
        <!-- use label= if user gave it. I like using a <div> instead of
             relying on the CAPTION tag working the way I expect -->
        <xsl:if test="string-length(@title)">
            <div class="table-title">    
                <xsl:value-of select="@title" />
            </div>        
        </xsl:if>
        
        <!-- Table is built with <tr>, <th>, <td> as usual ... -->
        <table class="table-body"><xsl:apply-templates /></table>
    </div>
</xsl:template>
The remainder of the table tags (<tr>, <th>, and <td>) are added by simply expanding the current list of copied tags:
Adding more standard tags ...
<!-- Pass along a number of standard HTML tags as-is -->
<xsl:template match="p|i|b|tt|ul|ol|li|tr|th|td">
    <xsl:copy>
        <xsl:apply-templates />
    </xsl:copy>
</xsl:template>
Here are the new styles related to table creation:
Table styling
div.table-container {
    margin-top: 2em;
    margin-bottom: 2em;
}

div.table-title {
    margin-left: 6em;
    margin-right: 6em;
    font-size: 1.2em;
    font-weight: bold;
    padding-bottom: 1em;
    text-align: center;
}

table.table-body {
    border: 1px solid #888888;
    border-collapse: collapse;
    padding: 0;
    margin: 0;
    background: #ddf3ff;

    margin-left: auto;
    margin-right: auto;
    font-size: 1em;
}

tr {
    border: 1px solid #888888;
    border-collapse: collapse;
    padding: 0;
    margin: 0;
}

th {
    border: 1px solid #888888;
    border-collapse: collapse;
    padding-left: .2em;
    padding-right: .2em;
    margin: 0;
    background: #eeeead;
    text-align: center;
}

td {
    border: 1px solid #888888;
    border-collapse: collapse;    
    margin: 0;
    padding-left: 0.5em;
    padding-right: 0.5em;
    text-align: center;
}
Sample Article
I've kept the sample article from the previous installment, and just added more to it to demonstrate the new features. You can view the result here: article.xml.

If you need to run the XSLT processing manually, here are the required files: