I have a field (<textarea name="desc" />
) that may contain newlines and I want to replace them with their HTML counterpart: <br />
. How can I do this? I'm using Thymeleaf 2.1.4.RELEASE.

- 2,404
- 2
- 29
- 33
3 Answers
As stated by dominik, \n
for newline does not work. However, you can use
.
${#strings.replace(desc,' ','<br>')}
Or with escaping to prevent code injection:
${#strings.replace(#strings.escapeXml(desc),' ','<br>')}

- 15,922
- 5
- 82
- 83
-
2Just to help people. is the ASCII of the LineFeed character. It worked like a charm :) – borjab Dec 23 '16 at 15:16
-
IntelliJ has some issues with parsing this correctly, but it does work when running it. – Rik Schaaf Dec 12 '20 at 18:41
As in JSP, it's not possible to use simple and straightforward
${#strings.replace(desc, '\n', '<br />')}
There are at least two problems:
- '\n' is treated by underlying expression language (SpEL in my case as I'm using Spring MVC) as string literal that consist of two separate characters: '\' and 'n' rather than single newline character
- exception is being thrown as the Thymeleaf underlying XML parser does not allow to put
<
and>
inside expressions
The solution I found for the first problem is to set newline character in a controller and pass it to view.
To address the second problem you need to use <
instead of <
and >
instead of >
. Also remember that this implies using th:utext
instead of th:text
// in controller:
model.addAttribute("newLineChar", '\n');
// in view
${#strings.replace(desc, newLineChar, '<br />')}
If you are using Thymeleaf + Spring (what means that Thymeleaf will use SpEL instead of OGNL), you may also use SpEL T operator
.This way you don't have to declare the newline variable in your controller but mind out that newline separator in this case will vary across operating systems that your app is running on:
${#strings.replace(desc, T(System).getProperty('line.separator'), '<br />')}
What I'm going to finally use is the combination of the above + Apache StringUtils that defines public static final String LF = "\n";
:
${#strings.replace(desc, T(org.apache.commons.lang3.StringUtils).LF, '<br />')}
-
2really? this does not work for me and looks like so complicated to do something trivial – Raul Lapeira Herrero Nov 13 '19 at 14:32
It's possible to do this with a custom dialect and attribute processor to handle doing this without a lot of inline SpEl or hacks.
Creating a Custom Attribute Processor
public class NewlineAttrProcessor extends AbstractUnescapedTextChildModifierAttrProcessor
{
public NewlineAttrProcessor()
{
super("nl2br");
}
@Override
protected String getText(Arguments arguments, Element element, String attributeName)
{
final Configuration configuration = arguments.getConfiguration();
final IStandardExpressionParser parser =
StandardExpressions.getExpressionParser(configuration);
final String attributeValue = element.getAttributeValue(attributeName);
final IStandardExpression expression =
parser.parseExpression(configuration, arguments, attributeValue);
final String value = (String)expression.execute(configuration, arguments);
return StringUtils.replace(value, "\n", "<br />");
}
@Override
public int getPrecedence()
{
return 10000;
}
}
You have to extend the AbstractUnescapedTextChildModifierAttrProcessor
processor or else you'll get the html entity tags for <br />
and you won't actually get a line break.
Creating a custom dialect
To implement a custom dialect you need a dialect class like so:
public class MyCustomDialect extends AbstractDialect
{
@Override
public String getPrefix()
{
return "cd";
}
@Override
public Set<IProcessor> getProcessors()
{
final Set<IProcessor> processors = new HashSet<>();
processors.add(new NewlineAttrProcessor());
return processors;
}
}
The getPrefix
method return value is what you would use to call any custom processors that you make. For example, Thymeleaf uses th
. The custom processor we implemented above this is looking for nl2br
so to call it you would use the cd:nl2br
attribute instead of th:text
.
Registering your new dialect
In your main class, you just need to create a @Bean
that will return a new instance of your dialect class.
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
@Bean
public MyCustomDialect myCustomDialect()
{
return new MyCustomDialect();
}
}
Using your custom processor
Finally, in your template file you would have an HTML tag like this:
<div cd:nl2br="${myObject.myField}">MY MULTILINE FIELD</div>
For a more thorough guide to implementing custom dialects I recommend the Thymeleaf docs:

- 6,209
- 3
- 45
- 69
"s that are invalid in .doc format - that's why it's not a job for controllers. – dominik Jun 15 '16 at 15:08