Thymeleaf: заменить символы новой строки с

у меня есть поле (<textarea name="desc" />), которые могут содержать новые строки, и я хочу заменить их на их HTML-аналог:<br />. Как я могу это сделать? Я использую Thymeleaf 2.1.4.ОСВОБОЖДАТЬ.

3 ответов


как заявил Доминик, \n для newline не работает. Однако, вы можете использовать &#10;.

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

или с побегом, чтобы предотвратить инъекцию кода:

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

как в JSP, невозможно использовать простой и понятный

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

есть по крайней мере две проблемы:

  • '\n 'обрабатывается базовым языком выражений (SpEL в моем случае, поскольку я использую Spring MVC) как строковый литерал, состоящий из двух отдельных символов:" \ " и "n", а не одного символа новой строки
  • исключение выбрасывается, поскольку базовый XML-анализатор Thymeleaf не позволяет поместить < и > внутри выражения

решение, которое я нашел для первой проблемы, - установить символ новой строки в контроллере и передать его на просмотр.

для решения второй проблемы нужно использовать &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.Таким образом, вам не нужно объявлять переменную newline в контроллере, но имейте в виду, что разделитель newline в этом случае будет отличаться в разных операционных системах, на которых работает ваше приложение:

${#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;')}

это можно сделать с помощью пользовательского процессора диалекта и атрибута, чтобы справиться с этим без большого количества встроенных 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 процессор, иначе вы получите теги сущности html для <br /> и вы на самом деле не сделать разрыв строки.

создание пользовательского диалект

для реализации пользовательского диалекта вы нужен класс диалекта, например:

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 поэтому, чтобы назвать его, вы бы использовали вместо th:text.

регистрация нового диалекта

в вашем основном классе вам просто нужно создать @Bean что вернется новый экземпляр класса dialect.

@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: