web-dev-qa-db-ja.com

PHP "プリティプリント" HTML(Tidyではない)

PHPでいくつかのHTMLドキュメントを作成するためにDOM拡張機能を使用していますが、出力を(新しい行とインデントを使用して)適切にフォーマットして、多くの人から読み取れるようにしたいです。私が行ったテスト:

  1. 「formatOutput = true」は、saveHTML()ではまったく機能せず、saveXML()でのみ機能します。
  2. SaveXML()を使用した場合でも、「preserveWhiteSpace = false」を使用しても、loadHTML()に含まれている要素ではなく、DOMを介して作成された要素でのみ機能します。

誰かが違うことを知っているなら、私は彼らがそれをどのように機能させたかを本当に知りたいです。

したがって、私はDOMドキュメントを持っており、saveHTML()を使用してHTMLを出力しています。有効であることがわかっているDOMからのものであるため、「整理」したり検証したりする必要はありません。

DOM拡張機能から受け取った出力から適切にフォーマットされた出力を取得する方法を探しています。

NB。ご想像のとおり、Tidy拡張機能をa)必要以上に多くのことを実行し(マークアップはすでに有効です)、b)実際にHTMLコンテンツに変更を加えます(など)。 HTML 5 doctypeといくつかの要素)

フォローアップ:

OK、以下の答えの助けを借りて、DOM拡張機能が機能しなかった理由を解明しました。与えられた例は機能しますが、それでも私のコードでは機能しませんでした。 this コメントの助けを借りて、isWhitespaceInElementContent()がtrueであるテキストノードがある場合、そのポイントを超えてフォーマットが適用されないことがわかりました。これは、preserveWhiteSpaceがfalseであるかどうかに関係なく発生します。解決策は、これらのノードをすべて削除することです(ただし、これが実際のコンテンツに悪影響を与える可能性があるかどうかはわかりません)。

29
Jack Sleight

そうです、HTMLにはインデントがないようです( 他の人も混乱しています )。 XMLは、ロードされたコードでも機能します。

<?php
function tidyHTML($buffer) {
    // load our document into a DOM object
    $dom = new DOMDocument();
    // we want Nice output
    $dom->preserveWhiteSpace = false;
    $dom->loadHTML($buffer);
    $dom->formatOutput = true;
    return($dom->saveHTML());
}

// start output buffering, using our Nice
// callback function to format the output.
ob_start("tidyHTML");

?>
<html>
    <head>
    <title>foo bar</title><meta name="bar" value="foo"><body><h1>bar foo</h1><p>It's like comparing apples to oranges.</p></body></html>
<?php
// this will be called implicitly, but we'll
// call it manually to illustrate the point.
ob_end_flush();
?>

結果:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<title>foo bar</title>
<meta name="bar" value="foo">
</head>
<body>
<h1>bar foo</h1>
<p>It's like comparing apples to oranges.</p>
</body>
</html>

saveXML()と同じ...

<?xml version="1.0" standalone="yes"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
  <head>
    <title>foo bar</title>
    <meta name="bar" value="foo"/>
  </head>
  <body>
    <h1>bar foo</h1>
    <p>It's like comparing apples to oranges.</p>
  </body>
</html>

loadHTMLの前にpreserveWhiteSpace = falseを設定するのをおそらく忘れましたか?

免責事項:私はデモコードのほとんどを tyson clugg/phpマニュアルコメント から盗みました。怠惰な私。


UPDATE:数年前に同じことを試し、同じ問題が発生したことを今でも覚えています。私はこれを汚い回避策を適用することで修正しました(パフォーマンスは重要ではありませんでした):問題がなくなるまで、SimpleXMLとDOMの間でなんとか変換しました。私は変換がそれらのノードを取り除いたと思います。多分domでロードし、simplexml_import_domでインポートしてから、文字列を出力し、これをDOMで再度解析して、次にきれいに出力します。私が覚えている限り、これはうまくいきました(しかし、それは本当に遅かったです)。

29
stefs

私がたくさんの名前空間XMLを持っていたとき、きちんとしたHTMLは気に入らなかった、これに出くわした:

http://gdatatips.blogspot.com/2008/11/xml-php-pretty-printer.html

6
Garvin

htmLawed ライブラリの hl_tidy 関数のコードを使用できます。

// indent using one tab per indent, with all HTML being within an imaginary div
$out = hl_tidy($in, 't', 'div')
0
user594694