Thymeleaf:用换句替换换行符

时间:2015-06-04 22:06:02

标签: java spring spring-mvc thymeleaf

我有一个可能包含换行符的字段(grep),我想用它们的HTML副词替换它们:$ tail a* ==> a1 <== hello 23 asd asdfasfd ==> a2 <== asdfasfd is 15 ==> a3 <== $ grep -ho '[0-9]*' a* | awk '{sum+=$1} END {print sum}' 38 。我怎样才能做到这一点?我正在使用Thymeleaf 2.1.4.RELEASE。

3 个答案:

答案 0 :(得分:10)

dominik 所述,换行符\n不起作用。但是,您可以使用&#10;

${#strings.replace(desc,'&#10;','&lt;br&gt;')}

或者通过转义来防止代码注入:

${#strings.replace(#strings.escapeXml(desc),'&#10;','&lt;br&gt;')}

答案 1 :(得分:8)

As in JSP,无法使用简单明了的

${#strings.replace(desc, '\n', '<br />')}

至少有两个问题:

  • &#39; \ n&#39;由底层表达式语言(在我的情况下为Spel,我使用Spring MVC)处理为由两个单独的字符组成的字符串文字:&#39; \&#39;和&#39; n&#39;而不是单个换行符
  • 由于Thymeleaf底层XML解析器不允许在表达式中放置<>,因此会抛出
  • 异常

我找到的第一个问题的解决方案是在控制器中设置换行符并将其传递给视图。

要解决第二个问题,您需要使用&lt;代替<&gt;而不是>。另请注意,这意味着使用th:utext代替th:text

// in controller:
model.addAttribute("newLineChar", '\n');

// in view
${#strings.replace(desc, newLineChar, '&lt;br /&gt;')}

如果您正在使用Thymeleaf + Spring(这意味着Thymeleaf将使用SpEL而不是OGNL),您也可以使用SpEL T operator。这样您就不必在您的内容中声明换行变量控制器,但请注意,在这种情况下,换行符分隔符会因应用程序运行的操作系统而异:

${#strings.replace(desc, T(System).getProperty('line.separator'), '&lt;br /&gt;')}

我最终要使用的是上述+ Apache StringUtils的组合,它们定义了public static final String LF = "\n";

${#strings.replace(desc, T(org.apache.commons.lang3.StringUtils).LF, '&lt;br /&gt;')}

答案 2 :(得分:1)

可以使用自定义方言和属性处理器执行此操作,以便在没有大量内联SpEl或黑客攻击的情况下执行此操作。

创建自定义属性处理器

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;
    }
}

您必须扩展AbstractUnescapedTextChildModifierAttrProcessor处理器,否则您将获得<br />的html实体标记,并且您实际上不会获得换行符。

制作自定义方言

要实现自定义方言,您需要一个类似的方言类:

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;
    }
}

getPrefix方法返回值是您用来调用您所做的任何自定义处理器的值。例如,Thymeleaf使用th。我们在上面实现的自定义处理器正在寻找nl2br,因此要调用它,您将使用cd:nl2br属性而不是th:text

注册新方言

在您的主课程中,您只需要创建一个@Bean,它将返回您的方言类的新实例。

@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

    @Bean
    public MyCustomDialect myCustomDialect()
    {
        return new MyCustomDialect();
    }
}

使用自定义处理器

最后,在您的模板文件中,您将拥有这样的HTML标记:

<div cd:nl2br="${myObject.myField}">MY MULTILINE FIELD</div>

有关实施自定义方言的更全面的指南,我建议使用Thymeleaf文档: