Filter Templates

The basic xsl filter shown below only accepts text from the original content.

This is because the filter matches the root node <xsl:template match="/">
and all of the nodes from the root <xsl:template match="*">
but only has a template to copy the content of the text <xsl:template match="text()">

This is fine if you want to strip all markup but that would not be a typical case.

Normally the template code would be very compact but in the following examples I show simple expanded templates to make it easier to follow what is going on.

I also include empty templates containing only comments to explain what is going on, but these are not needed in your real filter.

You can write your templates this way, it makes no difference to the xsl parser or the performance of your template transform, it's just more code to type but makes it clearer for others to follow.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" method="xml" indent="yes" cdata-section-elements="script"/> <xsl:template match="/">
<xsl:apply-templates select="*"/>
</xsl:template>

<xsl:template match="*">
<xsl:apply-templates select="node()"/>
</xsl:template> <xsl:template match="text()">
<xsl:value-of select="."/>
</xsl:template> </xsl:stylesheet>

If you want to allow editors to copy/paste and maintain the formatting we would add templates for the paragraph, heading, form and table elements we want to allow to be pasted in. 

HTML Elements

 <xsl:template match="p|em|strong|ul|ol|li|a|img|blockquote">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>
 <!--  Heading Elements  Permitted -->
 <xsl:template match="h1|h2|h3|h4|h5|h6">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>
 <!--  Form Elements Permitted -->
 <xsl:template match="form|legend|label|input|caption|fieldset|select|textarea|button|submit">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>
 <!--  Table Elements Permitted -->
 <xsl:template match="table|th|tr|td|thead|tbody|tfoot|caption">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

Now that we are copying html elements (tags) we need to be careful and handle the attributes that we want to allow on each element so that we can guarantee standards compliant html.

HTML Attributes

 <xsl:template match="@*">
  <!-- Filter out all Attributes except those permitted -->
 </xsl:template>
 <!-- Standard Attributes id, class, title, style, dir, lang, xml:lang -->
 <xsl:template match="@id|@title|@dir|@lang|@xml:lang">
  <xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
 </xsl:template>
 <!-- Permitted Label Element Attributes -->
 <xsl:template match="label/@for|label/@accesskey">
  <xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
 </xsl:template>
 <!-- Permitted Input Element Attributes -->
 <xsl:template match="input/@type|input/@value">
  <xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
 </xsl:template>
 <!-- Permitted Form Element Attributes -->
 <xsl:template match="form/@method|form/@action|form/@enctype">
  <xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
 </xsl:template>
 <!-- Permitted A Element Attributes -->
 <xsl:template match="a/@href">
  <xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
 </xsl:template>
 <!-- Permitted IMG Element Attributes -->
 <xsl:template match="img/@src|img/@alt|img/@width|img/@height|img/@longdesc">
  <xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
 </xsl:template>
 <!-- Permitted table Element Attributes -->
 <xsl:template match="table/@*|thead/@*|tbody/@*|th/@*|td/@*|tr/@*">
  <xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
 </xsl:template>

There may be old style HTML markup that we want to convert such as bold, italic, line breaks and horizontal rule.

HTML Element Convertion

 <!--  Bold Element Convertion  to strong text -->
 <xsl:template match="b">
  <xsl:element name="strong">
   <xsl:apply-templates select="node()|@*"/>
  </xsl:element>
 </xsl:template>
 <!--  Italic Element Convertion to emphasized text -->
 <xsl:template match="i">
  <xsl:element name="em">
   <xsl:apply-templates select="node()|@*"/>
  </xsl:element>
 </xsl:template>
 <!--  Span Element Convertion  -->
 <xsl:template match="span">
  <xsl:apply-templates select="node()|@*"/>
 </xsl:template>
 <!--  Div Element Convertion  -->
 <xsl:template match="div">
  <xsl:apply-templates select="node()|@*"/>
 </xsl:template>
 <!--  BR Element Convertion  -->
 <xsl:template match="br">
  <xsl:element name="br"/>
 </xsl:template>
 <!--  HR Element Convertion  -->
 <xsl:template match="hr">
  <xsl:element name="hr"/>
 </xsl:template>

The Tridion schema XSLT filter also requires a a couple of extra templates for the filter to work. These are the body, the R5GUIToolbar and the FormatingFeatures.

 

  <xsl:template match="body|R5GUIToolbar">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>
 <xsl:template match="@tcmuri">
  <xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
 </xsl:template>

<xsl:template name="FormattingFeatures">
  <FormattingFeatures xmlns="http://www.tridion.com/ContentManager/5.2/FormatArea">
   <Doctype>Strict</Doctype>
   <AccessibilityLevel>3</AccessibilityLevel>
   <DisallowedStyles/>
   <DisallowedActions>
    <Underline/>
    <AlignLeft/>
    <Center/>
    <AlignRight/>
    <Font/>
    <Background/>
    <TableHeight/>
    <TableHAlign/>
    <TableBackground/>
    <TableCellWidth/>
    <TableCellHeight/>
    <TableCellBackground/>
   </DisallowedActions>
  </FormattingFeatures>
 </xsl:template>

Created: Monday 24th May 2010 11:31 AM
Last Modified: Sunday 11th July 2010 6:52 PM LinkedIn link: View Chris Mills' profile on LinkedIn
Valid XHTML 1.0! Valid CSS! Level A conformance icon, W3C-WAI Web Content Accessibility Guidelines 1.0