我在PHP中使用DOM扩展来构建一些HTML文档,我希望输出格式很好(使用新的行和缩进),以便它可读,但是,我已经完成了很多测试:
如果有人知道不同,我真的很想知道他们是如何让它发挥作用的。
所以,我有一个DOM文档,我正在使用saveHTML()来输出HTML。由于它来自DOM,我知道它是有效的,没有必要以任何方式“整理”或验证它。
我只是在寻找一种从DOM扩展接收的输出中获得格式良好的输出的方法。
NB。正如您可能已经猜到的那样,我不想使用Tidy扩展作为a)它还需要它做更多(标记已经有效)和b)它实际上对HTML内容进行了更改(例如HTML 5 doctype和一些元素。)
跟进:
好的,在下面的答案的帮助下,我已经找出了DOM扩展无法正常工作的原因。虽然给定的示例有效,但仍然无法使用我的代码。在this注释的帮助下,我发现如果你有任何文本节点,其中isWhitespaceInElementContent()为true,则不会在该点之外应用格式化。无论preserveWhiteSpace是否为false,都会发生这种情况。解决方案是删除所有这些节点(虽然我不确定这是否会对实际内容产生负面影响)。
答案 0 :(得分:29)
你是对的,HTML似乎没有缩进(others are also confused)。即使加载了代码,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 manual comments窃取了大部分演示代码。懒我
更新:我现在记得几年前我尝试过同样的事情并遇到了同样的问题。我通过应用一个脏的解决方法(不是性能关键)修复了这个问题:我只是在SimpleXML和DOM之间转换,直到问题消失。我想转换摆脱了那些节点。也许用dom加载,用
simplexml_import_dom
导入,然后输出字符串,再次用DOM解析它,然后打印得很漂亮。据我所知,这有效(但它真的慢)。
答案 1 :(得分:6)
当我有一堆名称空间的XML tidyHTML不喜欢时,遇到了这个:
http://gdatatips.blogspot.com/2008/11/xml-php-pretty-printer.html
答案 2 :(得分:1)
结果:
<!DOCTYPE html>
<html>
<head>
<title>My website</title>
</head>
</html>
请考虑:
function indentContent($content, $tab="\t"){
$content = preg_replace('/(>)(<)(\/*)/', "$1\n$2$3", $content); // add marker linefeeds to aid the pretty-tokeniser (adds a linefeed between all tag-end boundaries)
$token = strtok($content, "\n"); // now indent the tags
$result = ''; // holds formatted version as it is built
$pad = 0; // initial indent
$matches = array(); // returns from preg_matches()
// scan each line and adjust indent based on opening/closing tags
while ($token !== false && strlen($token)>0){
$padPrev = $padPrev ?: $pad; // previous padding //Artis
$token = trim($token);
// test for the various tag states
if (preg_match('/.+<\/\w[^>]*>$/', $token, $matches)){// 1. open and closing tags on same line - no change
$indent=0;
}elseif(preg_match('/^<\/\w/', $token, $matches)){// 2. closing tag - outdent now
$pad--;
if($indent>0) $indent=0;
}elseif(preg_match('/^<\w[^>]*[^\/]>.*$/', $token, $matches)){// 3. opening tag - don't pad this one, only subsequent tags (only if it isn't a void tag)
foreach($matches as $m){
if (preg_match('/^<(area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)/im', $m)){// Void elements according to http://www.htmlandcsswebdesign.com/articles/voidel.php
$voidTag=true;
break;
}
}
$indent = 1;
}else{// 4. no indentation needed
$indent = 0;
}
$line = str_pad($token, strlen($token)+$pad, $tab, STR_PAD_LEFT);// pad the line with the required number of leading spaces
$result .= $line."\n"; // add to the cumulative result, with linefeed
$token = strtok("\n"); // get the next token
$pad += $indent; // update the pad size for subsequent lines
if($voidTag){
$voidTag=false;
$pad--;
}
}
return $result;
}
//$htmldoc - DOMdocument Object!
$niceHTMLwithTABS = indentContent($htmldoc->saveHTML(), $tab="\t");
echo $niceHTMLwithTABS;
将导致HTML具有以下内容:
该函数(这是我使用的类的一种方法)在很大程度上基于:https://stackoverflow.com/a/7840997/7646824
答案 3 :(得分:0)