CTFP TextFilter

Release 1.0 - ...

By setting up the right text filters in your site you can keep your editors shielded from the horror of repeated escaping of xml entities. A text filter defines strings or string patterns (using regular expressions) to be replaced when loading a field in the editor and a different (complementary) set of strings and patterns to be replaced when saving a field.

Text filters are defined in the ../System/TextFilters.xml file. Filters are identified by their id attribute on the textfilter element. An example of a very simple but also very useful filter:

XML CopyCode image Copy Code
<textfilter id="ampersands">
  <write>
    <find><![CDATA[&]]></find>
    <replace><![CDATA[&amp;]]></replace>
  </write>
  <read>
    <find><![CDATA[&amp;]]></find>
    <replace><![CDATA[&]]></replace>
  </read>
</textfilter>
Adding the ctfp TextFilter=ampersands to the Body field of a content type will make sure that all ampersands entered by the user are escaped when saved to the database. A more expansive filter can be created by adding write and read elements. You will typically have an equal number of write and read nodes to have symmetrical filtering.
XML CopyCode image Copy Code
<textfilter id="packSXML">
  <write><find>{</find><replace><![CDATA[&#123;]]></replace></write>
  <write><find>}</find><replace><![CDATA[&#125;]]></replace></write>
  <write>
    <find><![CDATA[&]]></find>
    <replace><![CDATA[&amp;]]></replace>
  </write>
  <read>
    <find type="string"><![CDATA[&amp;]]></find>
    <replace><![CDATA[&]]></replace>
  </read>
  <read><find><![CDATA[&#123;]]></find><replace>{</replace></read>
  <read><find><![CDATA[&#125;]]></find><replace>}</replace></read>
</textfilter>
The packSXML filter will disable vipers in the current field as well as escaping ampersands. Note that the filters are applied in order, so that the ampersands inserted by the first and second filter are escaped by the third one when writing and the ampersands are unescaped before replacing the accolades when reading. To make filters reusable, you can use the source attribute to specify another filter to be applied within your current text filter:
XML CopyCode image Copy Code
<write><find>{</find><replace><![CDATA[&#123;]]></replace></write>
<write><find>}</find><replace><![CDATA[&#125;]]></replace></write>
<write source="ampersands" />
Because vipers aren't part of the data in an item, text inside of vipers is ignored by the filtering unless a filter specifically sets the includevipers attribute to "true". All code examples on this page are rendered by the formatexample translation, but code inside the translation needs to be escaped. So we disable the formatexample viper first, then apply the actual filtering and re-enable formatexample:
XML CopyCode image Copy Code
<!-- Escape the formatexample viper to enable further replaces within -->
<write includevipers="true">
  <find>{formatexample(</find>
  <replace>{_formatexample(</replace>
</write>
 
<write source="viperexample" />
<write source="ampersands" />
 
<!-- Restore formatexample viper. -->
<write includevipers="true">
  <find>{_formatexample(</find>
  <replace>{formatexample(</replace>
</write>
The read filters are similar, of course. To create a filter matching a pattern add type="regex" to the find element:
XML CopyCode image Copy Code
<read>
  <find type="regex" attributes="g"><![CDATA[([Ss]martsite\s)?[Ff]alcon]]></find>
  <replace>$1iXperion</replace>
</read>
Accepted attributes are g for global, i for case-insensitive and m for multi-line. The filter handler just checks if these letters exist in the attributes string; the order in which the attributes are set and the inclusion of other letters are ignored.

New in RC2

Lessons learnt from working with compliance and character encoding in the manager of Smartsite 5.3 have found their way into the TextFilter handling of iXperion RC2. Specifically editor dependant filters. This means that a different filter is applied to the data for different editor progids. This is important because the webEditor will treat data differently than an html textarea both the incoming data and the data being sent back to the server. The appropriate filter is selected from a list of all filters with the correct id attribute. The first filter that matches the editprogid attribute (in lower case) or the first filter that doesn't specify this attribute is taken to be the correct filter. So define the editor-specific filters first and then define a catch-all filter for the rest:

XML CopyCode image Copy Code
<!-- WYSISWYG display for web editor 
  (Body field in Edit Item)
 -->
  <textfilter id="htmlfield" editprogid="sixswe.webeditor">
    <write source="escapenamedentities" />
    <read source="makewellformed" />
  </textfilter>
 
<!-- html view in text box. Numeric entities are rendered, all other entities are escaped 
  (Body field in Edit Item Plain)
 -->
  <textfilter id="htmlfield">
    <write source="escapenamedentities" />
  </textfilter>