Replace \r\n Newlines using XSLT and .NET C# VS 2008

12,322

Solution 1

The call template above looks OK, you just need the template to go with it!

<!-- XSL FILE -->


<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="1.0">
  <xsl:variable name="_crlf"><xsl:text>
</xsl:text></xsl:variable>
  <xsl:variable name="crlf" select="string($_crlf)"/>
  <xsl:template match="/">

    <xsl:for-each select="//demo">
      Demo:
      <xsl:call-template name="crlf-replace">
    <xsl:with-param name="subject" select="./text()"/>
      </xsl:call-template>
    </xsl:for-each>
  </xsl:template>

  <xsl:template name="crlf-replace">
    <xsl:param name="subject"/>

    <xsl:choose>
      <xsl:when test="contains($subject, $crlf)">
    <xsl:value-of select="substring-before($subject, $crlf)"/><br/>
    <xsl:call-template name="crlf-replace">
      <xsl:with-param name="subject" select="substring-after($subject, $crlf)"/>
    </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
    <xsl:value-of select="$subject"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>


<!-- XML FILE -->

<?xml version="1.0"?>

<demos>
  <demo>xslt is really fun</demo>
  <demo>you quite often use recursion in xslt</demo>
  <demo>so there!</demo>
</demos>

Solution 2

There are two problems here:

  1. You should not try to replace CRLF -- such a string isn't present in the text. The reason for this is that any compliant XML parser normalizes the text nodes by replacing any CR+LF combination with a single LF (&#xA). The W3C XML Specification says: "To simplify the tasks of applications, wherever an external parsed entity or the literal entity value of an internal parsed entity contains either the literal two-character sequence "#xD#xA" or a standalone literal #xD, an XML processor must pass to the application the single character #xA. (This behavior can conveniently be produced by normalizing all line breaks to #xA on input, before parsing.) "

  2. The replacement shouldn't be a string. It should be a node -- <br />.

Fixing these two problems is easy:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <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="text()" name="replaceNL">
  <xsl:param name="pText" select="."/>

  <xsl:choose>
    <xsl:when test="contains($pText, '&#xA;')">
      <xsl:value-of select=
        "substring-before($pText, '&#xA;')"/>
      <br />
      <xsl:call-template name="replaceNL">
        <xsl:with-param name="pText" select=
          "substring-after($pText, '&#xA;')"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$pText"/>
    </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on this XML document:

<Exception>
 <Description>Quite common error:
 Missing '('
 </Description>
 <Message>Error1001:
 Syntax error 2002
 </Message>
 <DateTime>localTimeString</DateTime>
</Exception>

the wanted, correct result is produced:

<Exception>
    <Description>Quite common error:<br/> Missing '('<br/> </Description>
    <Message>Error1001:<br/> Syntax error 2002<br/> </Message>
    <DateTime>localTimeString</DateTime>
</Exception>
Share:
12,322
Kiquenet
Author by

Kiquenet

Should "Hi", "Thanks" and taglines and salutations be removed from posts? http://meta.stackexchange.com/questions/2950/should-hi-thanks-and-taglines-and-salutations-be-removed-from-posts What have you tried? http://meta.stackexchange.com/questions/122986/is-it-ok-to-leave-what-have-you-tried-comments Asking http://stackoverflow.com/help/asking Answer http://meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers http://www.enriquepradosvaliente.com http://kiquenet.wordpress.com ◣◥◢◤◢◤◣◥◢◤◢◤◣◥◢◤ ◥◢◤◢◤◣◥◢◤◢◤◣◥◢◤◢ .NET developer and fan of continuous self-improvement and good patterns and practices. Stuff I am interested in: .NET technology stack in general, C#, Powershell and Javascript in particular as languages Test driven development, DI, IoC and mocking frameworks Data access with ORMs and SQL ASP.NET javascript, jQuery and related frontend frameworks Open source projects

Updated on June 04, 2022

Comments

  • Kiquenet
    Kiquenet almost 2 years

    I use VS 2008, .net 3.5 for generate page html using XSLT.

    I have Message, that contains \r\n (newlines)

    I use this in XSL file:

    <b>Message: </b><xsl:value-of select="Message"/><br/>
    

    I need replace \r\n by <br/> in xsl. I have seen several references but not get solution for my issue:

    I use this code C# before I call to transform XSLT, but not right:

     m = m.Replace(@"\r\n", "&#xD;&#xA;");
                m = m.Replace(@"\n", "&#xA;");
                //m = System.Web.HttpUtility.HtmlDecode(m);
    
                m = m.Replace(@"\r\n", "<br/>");
                m = m.Replace(@"\n", "<br/>");
                msg = "<Exception>"
                + "<Description>" + d + "</Description>"
                + "<Message>" + m + "</Message>"
                + "<DateTime>" + localTimeString + "</DateTime>"
                + "</Exception>";
    

    I use this references, but not solution

    Interpreting newlines with xsl:text?

    XSLT Replace function not found

    The replace function is only available in XSLT version 2.0, not in version 1.0 which is what Visual Studio uses. Just because you've specified version="2.0" doesn't mean that Visual Studio supports it.

    I use this like the last reference, but I get error:

     <xsl:call-template name="string-replace-all">
          <xsl:with-param name="text" select="Message"/>
          <xsl:with-param name="replace" select="\r\n"/>
          <xsl:with-param name="by" select="&lt;br/&gt;"/>
     </xsl:call-template>
    

    suggestions, any sample code works ?