12

I have a question on the default provided XSLT used for rich-text fields. A client is requesting a more rigid XSLT (to block script tags etc.) Anybody has some examples of finished XSL files ?

I've seen that between new versions of Tridion (5.3 -> 2009 -> 2011) this file hasn't changed a lot (except namespaces) and I wonder if someone could share their version of a customized XSL.

  • There were changes between 2009, 2011, and 2011 SP1 to handle cross-browser differences. – Alvin Reyes Mar 30 '13 at 5:47
15

One of the last ones I used was for 2011 and it stripped out a lot of unwanted elements and attributes (in the hope to the keep the source clear most of the times ;o).

It's documented what does what, hope its helpful to you:

<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <output omit-xml-declaration="yes" method="xml" cdata-section-elements="script"/>
  <template match="/ | node() | @*">
    <copy>
      <apply-templates select="node() | @*"/>
    </copy>
  </template>
  <template match="*[      (self::br or self::p or self::div)     and      normalize-space(translate(., &apos; &apos;, &apos;&apos;)) = &apos;&apos;     and      not(@*)     and      not(processing-instruction())     and      not(comment())     and      not(*[not(self::br) or @* or * or node()])     and      not(following::node()[not(         (self::text() or self::br or self::p or self::div)        and         normalize-space(translate(., &apos; &apos;, &apos;&apos;)) = &apos;&apos;        and         not(@*)        and         not(processing-instruction())        and         not(comment())        and         not(*[not(self::br) or @* or * or node()])       )])     ]">
    <!-- ignore all paragraphs and line-breaks at the end that have nothing but (non-breaking) spaces and line breaks -->
  </template>
  <template match="br[parent::div and not(preceding-sibling::node()) and not(following-sibling::node())]">
    <!-- Chrome generates <div><br/></div>. Renders differently in different browsers. Replace it with a non-breaking space -->
    <text> </text>
  </template>
  <!-- remove disallowed elements but keep its children -->
  <template match="font | h1 | h2 | h3 | h4 | h5 | h6 | hr | img | em">
    <apply-templates/>
  </template>
  <!-- remove dissallowed attributes -->
  <template match="@align | @valign | @border | @cellpadding | @cellspacing"/>
  <!-- remove all style attributes except those for a table cel to allow center alignment -->
  <template match="*[not(local-name() = &apos;td&apos;)]/@style"/>
  <template match="td/@style">
    <if test="contains(.,&apos;text-align&apos;)">
      <attribute name="style">
        <text>text-align:center;</text>
      </attribute>
    </if>
  </template>
  <!-- remove rowspan and collspan when set to 1 -->
  <template match="@colspan[.=&apos;1&apos;] | @rowspan[.=&apos;1&apos;]"/>
</stylesheet>
  • +1, nice example, Bart. The center alignment point is a good one--to allow authors the ability to center on elements, we shouldn't strip all attributes. – Alvin Reyes Mar 26 '13 at 14:31
0

Filter Templates

Originally Posted here in May 2010.

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>

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

HTML Element Conversion

<!--  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>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.