I originally posted this answer on a previous SO question but this one also seems to pop up. I've modified it to output a table instead of just newlines.
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);
final String[] lines = StringUtils.split(value, "\n");
return "<table><td>" + StringUtils.join(lines, "</td><td>") + "</td></table>";
}
@Override
public int getPrecedence()
{
return 10000;
}
}
You have to extend the AbstractUnescapedTextChildModifierAttrProcessor
processor or else you'll get the html entity tags for <table>...</table>
and you won't actually get the HTML.
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: