对于我正在构建的系统,我正在定义一个存储在LINKSTYLE
中的通用style
,该应该应用于尚未样式化(内联(a
元素。我对DOMDocument
或xpath
不是很有经验,我无法弄清楚出了什么问题。
感谢戈登,我更新了我的代码:
libxml_use_internal_errors(true);
$html = '<a href="#">test</a>'.
'<a href="#" style="border:1px solid #000;">test2</a>';
$dom = new DOMDocument();
$dom->loadHtml($html);
$dom->normalizeDocument();
$xpath = new DOMXPath($dom);
foreach($xpath->query('//a[not(@style)]') as $node)
$node->setAttribute('style','border:1px solid #000');
return $html;
有了这个更新的代码,我不再收到错误,但是a
元素没有样式化。
使用 libxml_use_internal_errors(true)
来抑制由 loadHTML
引起的解析错误。
-
libxml_use_internal_errors()
— 禁用 libxml 错误并允许用户获取错误信息
XPath 查询无效,因为contains
需要在样式属性中搜索值。
-
fn:contains($arg1 as xs:string?, $arg2 as xs:string?) as xs:boolean
如果要查找没有样式元素的所有锚点,只需使用
//a[not(@style)]
您看不到更改,因为您正在返回存储在 $html 中的字符串。使用 DOMDocument 加载字符串后,必须在运行查询并修改该字符串的 DOMDocument 内部表示形式后将其序列化回来。
示例(演示(
$html = <<< HTML
<ul>
<li><a href="#foo" style="font-weight:bold">foo</a></li>
<li><a href="#bar">bar</a></li>
<li><a href="#baz">baz</a></li>
</ul>
HTML;
$dom = new DOMDocument;
$dom->loadHTML($html);
$xp = new DOMXpath($dom);
foreach ($xp->query('//a[not(@style)]') as $node) {
$node->setAttribute('style', 'font-weight:bold');
}
echo $dom->saveHTML($dom->getElementsByTagName('ul')->item(0));
输出:
<ul>
<li><a href="#foo" style="font-weight:bold">foo</a></li>
<li><a href="#bar" style="font-weight:bold">bar</a></li>
<li><a href="#baz" style="font-weight:bold">baz</a></li>
</ul>
请注意,为了将saveHTML
与参数一起使用,您至少需要 PHP 5.3.6。
当您在文档内将&
用于创建实体引用以外的其他目的(例如 "
(。
通常,当您分隔 GET 参数时,这会发生在 URL 中。
您可以使用 Gordon 的建议忽略此错误或修复它(将&
的出现次数替换为 &
(。
我想知道是否有可能更 CCS 地解决这个问题,例如使用选择器。在 CSS3 中,可以只处理那些没有 style
属性的<a>
标记:
a:not([style]) {border:1px solid #000;}
因此,如果您的文档已经有样式表,则可以轻松添加。
如果没有,则必须将<style>
添加到文档中。这也可以用DomDocument完成,但我发现它有点复杂。然而,我让它为一些小游戏工作:
libxml_use_internal_errors(true);
$html = '<a href="#">test</a>'.
'<a href="#" style="border:1px solid #000;">test2</a>';
$dom = new DOMDocument();
$dom->loadHtml($html);
$dom->normalizeDocument();
// ensure that there is a head element, body will always be there
// because of loadHtml();
$head = $dom->getElementsByTagName('head');
if (0 == $head->length) {
$head = $dom->createElement('head');
$body = $dom->getElementsByTagName('body')->item(0);
$head = $body->parentNode->insertBefore($head, $body);
} else {
$head=$head->item(0);
}
// append style tag to head.
$css = 'a:not([style]) {border:1px solid #000;}';
$style = $dom->createElement('style');
$style->nodeValue=$css;
$head->appendChild($style);
$dom->formatOutput = true;
$output = $dom->saveHtml();
echo $output;
示例输出:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head><style>a:not([style]) {border:1px solid #000;}</style></head>
<body>
<a href="#">test</a><a href="#" style="border:1px solid #000;">test2</a>
</body>
</html>
如果 CSS 与其他更高的选择器发生冲突,这不是一个简单的解决方案。 不过!important
可能会有所帮助。
网页片段
就获取更改的 HTML 片段而言,这是一些可以与戈登建议一起使用的附加代码。只是正文标签的内部html,这次我玩了一下SPL:
// get html fragment
$output = implode('', array_map(
function($node) use ($dom) { return $dom->saveXml($node); },
iterator_to_array($xpath->query('//body/*'), false)))
;
foreach 绝对更具可读性和内存友好性:
// get html fragment
$output = '';
foreach($xpath->query('//body/*') as $node)
$output .= $dom->saveXml($node)
;