Jinja2の上で数値文字参照を変換したい

Python で Jinja2 テンプレートエンジンを使ったときに,数値文字参照が正しく変換されずに & で始まる文字列になってしまったのを解決するまでのお話です.

文字参照

& で始まり ; で終わる文字列で,(たぶんブラウザが) 自動的に変換して文字として表示してくれます.HTML で表記できない文字を表示するための方法です.

HTML では数値文字参照 (10 進数, 16 進数) と文字実体参照があります.

文字実体参照で有名なのは   で半角スペースとか,© で © とか.

数値文字参照 (10 進数) を用いて「数値文字参照」と書くと「数値文字参照」となります.

文字列に変換したい

プログラム上でスクレイピングしただけでは変換されないので文字になっていません.

数値文字参照を文字列に変換するモジュールはないようなので,過去に書いてくれた人のプログラムを参考にしてみます.

import re

s1 = '変換したい文字列'
s2 = []

for e in re.findall('&#x([0-9a-fA-F]+);', s1):
    s2.append(chr(int(e, 16)))

print(s2)

正規表現を使って数値文字参照での一文字分を取ってきて変換している感じです.このプログラムは 16 進数の数値文字参照に対応しているようですが,書き換えれば 10 進数もできるでしょう.

参考

数値文字参照を文字に変換する Python スクリプト | n-diary

Jinja2 上で処理させたい

上記したプログラムによる変換の精度はほぼ完璧でした.

ただ,一点.正規表現での取得の仕方から,変換前の文字列に含まれていたスペースが抜けてしまうということで断念.

取得してきた数値文字参照の文字列をそのまま HTML 上で出力させようかと思いましたが,& を & に変換してしまうため,うまくいきません.

そこで & を数値文字参照に変換せずにそのまま出力できぬものかと検索した結果,Jinja2 の機能が利用できました.

変換せずに出力したい変数 word に対して次のような処理をさせます.

{{word|safe}}

これだけで OK !

気付かないだけでいろんな機能がついてるんですね.

参考

Prevent “&” from being converted to “&” in Jinja | Stack Overflow