整形したいデータ
以下の壊れたHTMLが $html
に代入されているとします。
テストデータ
<html>
<p>
<a href="http://google.com/?q=あいうえお">あいうえおで検索</a>
<br>
<img src="hoge.jpg" alt="<'あいうえお'>">
A & B ><
<p></p>
整形する方法
Tidy を使う
最も「イイカンジ」に整形してくれて尚且つ実行速度も速いものはこれだと思います。但し、環境によっては拡張インストールが必要です。
テストコード
echo tidy_repair_string($html, ['indent' => true], 'utf8');
出力結果
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title></title>
</head>
<body>
<p>
<a href=
"http://google.com/?q=%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A">
あいうえおで検索</a><br>
<img src="hoge.jpg" alt="<'あいうえお'>"> A & B ><
</p>
</body>
</html>
何で indent-attributes
有効化してないのに href
の後で改行されてるんですかねぇ(憤怒
HTML Purifier を使う
ホワイトリスト方針のため、XSS防止における信頼性は抜群です。但し、ライブラリの設置が必要です。
テストコード
使った事が無くて最適なオプションを設定できる自信がないので誰か編集リクエストお願いします
出力結果
使った事が無くて最適なオプションを設定できる自信がないので誰か編集リクエストお願いします
DOM を使う
インデントを整えられないなど動作にやや不十分な点がありますが、拡張インストールやライブラリ無しで使えるメリットは大きいでしょう。
関数定義
function dom_repair_string($html) {
static $dom;
static $conv;
static $rev;
if ($dom === null) {
$dom = new DOMDocument;
$conv = function ($html) {
return mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');
};
$rev = function ($matches) {
return mb_convert_encoding($matches[0], 'UTF-8', 'HTML-ENTITIES');
};
}
@$dom->loadHTML($conv($html));
return preg_replace_callback('/(?:&#\d++;)++/', $rev, $dom->saveHTML());
}
テストコード
echo dom_repair_string($html);
出力結果
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p>
<a href="http://google.com/?q=%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A">あいうえおで検索</a>
<br><img src="hoge.jpg" alt="<'あいうえお'>">
A & B ></p></body></html>