Element Domain Specialization Step 5-2: Implement Type-Specific XSLT Templates

The different element types in the XML domain require different "decorations" on output to visually distinguish them. This could be done via CSS if we put appropriate @class values on the HTML output or it can be done here using literal text. The advantage of using literal text is that it will work even when the CSS isn't present or supported by the browser. The advantage of using CSS is that you can change look without regenerating the HTML. For this tutorial the point is to learn to do some stuff with XSLT so we are going to use literal text.

The pattern for each element's template is the same:
  <xsl:template match="*[contains(@class, ' xml-d/typename ')]">
    <code>
      <xsl:text>text before</xsl:text>
      <xsl:apply-templates/>
      <xsl:text>text after</xsl:text>
    </code>
  </xsl:template>

The @priority attribute ensures that this template will be used instead of any imported template. The <xsl:text> elements hold the generated text. This could be replaced with other HTML elements if you wanted some more complicated effect, like blue brackets or a superscript or something.

Note the leading and trailing spaces around the class attribute value (" xml-d/xmlelem "). It is very important to include those spaces so that you only match on the specific element types you want and not on types whose name happens to begin with the same letters.

The template uses the <code> element as the main HTML element for the XML components as it seems to be the closest match for the semantic of these keywords and we want the default HTML behavior of putting the text into a monospaced font.

For the <xmlelem> element, we need to generate the bounding angle brackets. Using the above model template as a template, create this template following the include statement in the xmlDomain2HTML.xsl file:
  <xsl:template match="*[contains(@class, ' xml-d/xmlelem ')]" priority="10">
    <code>
      <xsl:text>&lt;</xsl:text>
      <xsl:apply-templates/>
      <xsl:text>&gt;</xsl:text>
    </code>
  </xsl:template>

The other templates are just like this one, differing only in the text before and text after they produce. Simply cut and paste the template for <xmlelem> and modify it as needed for each of the other types.

The complete XSLT stylesheet should look like this:
<?xml version="1.0" encoding="UTF-8" ?>
<!-- ===========================================================
     HTML generation templates for the xmlDomain DITA domain.
     
     Copyright (c) 2010 Your Name Here
     
     =========================================================== -->

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="*[contains(@class, ' xml-d/xmlelem ')]" priority="10">
    <code>
      <xsl:text>&lt;</xsl:text>
      <xsl:apply-templates/>
      <xsl:text>></xsl:text>
    </code>
  </xsl:template>

  <xsl:template match="*[contains(@class, ' xml-d/xmlatt ')]" priority="10">
    <code>
      <xsl:text>@</xsl:text>
      <xsl:apply-templates/>
    </code>
  </xsl:template>

  <xsl:template match="*[contains(@class, ' xml-d/textent ')]" priority="10">
    <code>
      <xsl:text>&amp;</xsl:text>
      <xsl:apply-templates/>
      <xsl:text>;</xsl:text>
    </code>
  </xsl:template>

  <xsl:template match="*[contains(@class, ' xml-d/parment ')]" priority="10">
    <code>
      <xsl:text>%</xsl:text>
      <xsl:apply-templates/>
      <xsl:text>;</xsl:text>
    </code>
  </xsl:template>

  <xsl:template match="*[contains(@class, ' xml-d/numcharref ')]" priority="10">
    <code>
      <xsl:text>&amp;#</xsl:text>
      <xsl:apply-templates/>
      <xsl:text>;</xsl:text>
    </code>
  </xsl:template>
</xsl:stylesheet>

That's all there is to it, at least for these relatively simple keyword-based specializations. A specialization of something more sophisticated, like <simple-table> or <dl> could, of course, require more work. But just adding a few <ph> or <keyword> specializations and styling them is simple enough that anyone should be able to do it if they need to.

For XSL-FO output, the stylesheet would be almost the same, except that you would be generating <fo:inline> elements instead of HTML <code> or <span> elements.