对于我正在构建的系统,我正在定义存储在style
中的一般LINKSTYLE
,应该应用于尚未设置样式的a
元素(内联)。我对DOMDocument
或xpath
不是很有经验,我无法弄清楚出了什么问题。
感谢Gordon我更新了我的代码:
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
元素无法设置样式。
答案 0 :(得分:2)
使用libxml_use_internal_errors(true)
来抑制源自loadHTML
的解析错误。
XPath查询无效,因为contains
需要在style属性中搜索值。
如果要查找没有样式元素的所有锚点,只需使用
即可//a[not(@style)]
您没有看到您的更改,因为您正在返回存储在$ html中的字符串。使用DOMDocument加载字符串后,必须在运行查询并修改DOMDocument对该字符串的内部表示后对其进行序列化。
示例(demo)
$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
with an argument, you need at least PHP 5.3.6.
答案 1 :(得分:1)
当您使用内部文档&
用于创建实体引用(例如"
)之外的其他目的时,会发生第一个错误(编辑之前)。
通常,当您分隔GET参数时,会在URL中发生这种情况。
您可以使用Gordon的建议忽略此错误或修复它(用&
替换&
的出现。)
答案 2 :(得分:1)
我想知道是否有可能以更多的CCS方式解决这个问题,例如:用选择器。在CSS3中,只能处理那些没有<a>
属性的style
代码:
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片段,这是一些可以与gordons建议一起使用的附加代码。只是body标签的内部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)
;