LoginSignup
29
26

More than 5 years have passed since last update.

Thymeleafで改行コードをhtmlの改行タグに変換して出力する

Posted at

Thymeleafで改行を含んだ文字列を th:text 等で出力しても、改行は画面に反映されません。
改行コードを<br/>タグへ変換してあげる必要があります。

環境

  • Java 1.8
  • spring-boot 1.5.6.RELEASE
  • Thymeleaf 2.1.5

ポイント

  • 改行コード(\r, \n, \r\n)を<br/>に変換する。
  • 変換した<br/>タグ以外のhtmlタグはエスケープする。

実装

2通りの方法があるので紹介します。

① View上で実装

既存のThymeleaf構文のみを使用。
事前の設定等はいらないので気軽に使用可能。

<th:block th:if="${sentence}">
    <th:block th:each="str, stat : ${sentence.split('\r\n|\r|\n', -1)}">
        <th:block th:text="${str}"/>
        <br th:if="${!stat.last}"/>
    </th:block>
</th:block>

出力したい文字を改行コードで分割して th:each でループ。
中身を th:text で出力しつつ、間に<br/>を挿入しているだけである。

② 独自ダイアレクトを定義

上記の実装は手軽だが、複数個所で使用するとなると煩雑になってしまいます。
そこで独自ダイアレクトを作成してViewから参照できるようにします。

変換処理とテキスト出力するプロセッサ

TextLineProcessor.java
import org.thymeleaf.Arguments;
import org.thymeleaf.Configuration;
import org.thymeleaf.dom.Element;
import org.thymeleaf.processor.attr.AbstractUnescapedTextChildModifierAttrProcessor;
import org.thymeleaf.standard.expression.IStandardExpression;
import org.thymeleaf.standard.expression.IStandardExpressionParser;
import org.thymeleaf.standard.expression.StandardExpressionExecutionContext;
import org.thymeleaf.standard.expression.StandardExpressions;
import org.unbescape.html.HtmlEscape;


/**
 * 改行コードをbrタグに変換するプロセッサ
 */
public class TextLineProcessor extends AbstractUnescapedTextChildModifierAttrProcessor {

    public static final int ATTR_PRECEDENCE = 1450;
    public static final String ATTR_NAME = "textbr";


    protected TextLineProcessor() {
        super(ATTR_NAME);
    }


    @Override
    public int getPrecedence() {
        return ATTR_PRECEDENCE;
    }


    /**
     * 出力する文字列を返す
     *
     * @param arguments
     * @param element
     * @param attributeName
     * @return
     */
    @Override
    protected final String getText(
            final Arguments arguments, final Element element, final String attributeName) {

        String text = getAttributeObjectString(arguments, element, attributeName);

        // htmlエスケープ処理
        text = HtmlEscape.escapeHtml4Xml(text);

        // 改行コードをbrタグへ置換
        return text.replaceAll("\r\n|\r|\n", "<br/>");
    }


    /**
     * 属性に指定された変数を文字列として取得する
     *
     * @param arguments
     * @param element
     * @param attributeName
     * @return
     */
    protected String getAttributeObjectString(
            final Arguments arguments, final Element element, final String attributeName) {

        final String attributeValue = element.getAttributeValue(attributeName);

        final Configuration configuration = arguments.getConfiguration();
        final IStandardExpressionParser expressionParser = StandardExpressions.getExpressionParser(configuration);

        final IStandardExpression expression = expressionParser.parseExpression(configuration, arguments, attributeValue);

        final Object result =
                expression.execute(configuration, arguments, StandardExpressionExecutionContext.UNESCAPED_EXPRESSION);

        return (result == null ? "" : result.toString());

    }
}

th:textth:utext の処理を参考に実装しました。
簡単に処理を説明すると・・・
 1. htmlタグのエスケープ処理
 2. 改行コードを<br/>タグへ置換
 3. それをエスケープせずに画面出力

ダイアレクトの登録
作成したプロセッサをダイアレクトに登録する。

CustomDialect.java
import org.thymeleaf.dialect.AbstractDialect;
import org.thymeleaf.processor.IProcessor;

import java.util.HashSet;
import java.util.Set;


/**
 * 独自定義したダイアレクトを登録する
 */
public class CustomDialect extends AbstractDialect{

    static final String DIALECT_PREFIX = "ex";

    @Override
    public String getPrefix() {
        return DIALECT_PREFIX;
    }


    @Override
    public Set<IProcessor> getProcessors() {
        final Set<IProcessor> processors = new HashSet<IProcessor>();
        processors.add(new TextLineProcessor());
        return processors;
    }
}

Thymeleaf設定

ThymeleafConfiguration.java
import com.ushidatmhr.thymeleaf.CustomDialect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ThymeleafConfiguration {

    @Bean
    CustomDialect myDialect() {
        return new CustomDialect();
    }

}

使い方

<p ex:textbr="${sentence}" />
29
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
26