9

To restrict the p tags and br tags in Tridion RTF fields I am writing XSLT code. But at any time only one tag I can able to remove with the following code. Please correct me where I am doing wrong. Input XML:

    <html>
     <body>
      <p>This is the content in p tag.</p>
       <br/><br/>
       Content after br tag.
     </body>
    </html>

Expected output:

<html>
   <body>
      This is the content in p tag.Content after br tag.      
   </body>
</html>

XSLT written in Schema source:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:xh="http://www.w3.org/1999/xhtml">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>
 <xsl:template match="p|br">
    <xsl:apply-templates/>
  </xsl:template>
</xsl:stylesheet>

When I am trying the same code in online XSLT editors it is working fine. But when I test in Tridion it is not working. I also referred Bart Koopman post for this question. Thanks in Advance.

2 Answers 2

9

As for the XSLT required, try using the following Filtering XSLT

<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <output omit-xml-declaration="yes" method="xml" cdata-section-elements="script"></output>
  <template match="/ | node() | @*">
    <copy>
      <apply-templates select="node() | @*"></apply-templates>
    </copy>
  </template>
  <template match="p|br">
    <apply-templates></apply-templates>
  </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>
</stylesheet>

This removes the <p> and <br/> on Save or when you switch between the Design and Source tab of your Format Area. The trick is to place the removal of these element above the default handing of p and br (although you can probably experiment with removing those, or adjusting them a bit).

2
  • What will happen if in source document XHTML tags will have NS attached, e.g.: <p xmlns="w3.org/1999/xhtml">? My experiments (using XslCompiledTransform class) show that such <p/> will be stripped off. Is there any cure for this?
    – esteewhy
    Commented Aug 21, 2013 at 7:47
  • I think the content of an RTF field is considered XHTML, so that should just work. But I'm not sure how the exact inner details of it all work though. Commented Aug 21, 2013 at 14:02
4

Bart answer was the one you need to use.

You need to include the default tridion template part (that is first 3 templates) and then you need to add your required template match.

<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="p|br">
        <apply-templates/>
    </template>
</stylesheet>
4
  • Those two other templates already exist in the schema source. Still I am unable to achieve it. Are you able to remove two tags? Please help me out. Commented Apr 8, 2013 at 6:54
  • @P.Muralikrishna: Have you tried copy and pasting the template on the Filtered XSLT tab, with the one I gave? Commented Apr 8, 2013 at 7:13
  • 1
    @P.Muralikrishna: After adding the XSLT, please close the browser, clear browser cache and then open it again. Commented Apr 8, 2013 at 7:15
  • Just clearing the cache and re arranging the templates as Bart said solved my issue. Commented Apr 8, 2013 at 10:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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