Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 使用DOM和xpath设置非样式链接的样式_Php_Xpath_Domdocument - Fatal编程技术网

Php 使用DOM和xpath设置非样式链接的样式

Php 使用DOM和xpath设置非样式链接的样式,php,xpath,domdocument,Php,Xpath,Domdocument,对于我正在构建的系统,我正在定义一个存储在LINKSTYLE中的常规样式,该样式应应用于尚未设置样式(内联)的a元素。我对DOMDocument或xpath不是很有经验,我不知道哪里出了问题 多亏了Gordon,我更新了代码: libxml_use_internal_errors(true); $html = '<a href="#">test</a>'. '<a href="#" style="border:1px solid #00

对于我正在构建的系统,我正在定义一个存储在
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;
libxml\u使用\u内部错误(true);
$html=''。
'';
$dom=新的DOMDocument();
$dom->loadHtml($html);
$dom->normalizeDocument();
$xpath=newdomxpath($dom);
foreach($xpath->query('//a[not(@style)]')作为$node)
$node->setAttribute('style','border:1px solid#000');
返回$html;

有了这个更新的代码,我不再收到错误,但是
a
元素没有样式。

使用
libxml\u Use\u internal\u errors(true)
来抑制源于
loadHTML
的解析错误

XPath查询无效,因为
包含
需要在样式属性中搜索一个值

如果要查找没有样式元素的所有锚定,只需使用

//a[not(@style)]
您没有看到您的更改,因为您正在返回存储在$html中的字符串。一旦用DOMDocument加载了字符串,在运行查询并修改了DOMDocument对该字符串的内部表示之后,必须将其序列化回来

示例()

$html=query('//a[not(@style)])作为$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>
请注意,为了使用第一个错误(编辑前)发生在您将文档a内部
&
用于创建实体引用以外的其他目的时(例如

在URL中,当您分隔GET参数时,通常会发生这种情况


您可以使用Gordon的建议忽略或修复此错误(用
&;
替换
&;
)。

我想知道是否可以更明智地解决此问题,例如使用选择器。在CSS3中,可以只处理那些不具有
style
属性的
标记:

a:not([style]) {border:1px solid #000;}
因此,如果您的文档已经有了样式表,那么可以很容易地添加它

如果没有,则必须向文档中添加一个
。这也可以使用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;
foreach绝对更具可读性和内存友好性:

// get html fragment
$output = '';
foreach($xpath->query('//body/*') as $node) 
  $output .= $dom->saveXml($node)
  ;

嘿,那么解析错误可能来自非100%有效的HTML?现在,当我将xpath更改为您所说的内容时,我不再得到错误,但是
a
元素没有样式。我已经为我的问题添加了一个测试用例。@Kokos DOM扩展在下面使用libxml。当您使用
loadHTML
libxml时,将使用其HTML解析器模块它可以读取损坏的HTML。但为了实现这一点,解析器模块将添加隐含元素,这意味着当您仅执行
saveHTML
,您将添加一个DocType、一个HTML和body标记。如果您操作的是完整的HTML文档,这不是问题,因为这些元素无论如何都会存在(因此没有添加任何内容)。您的示例只显示了一个部分文档,这很重要,因为您不会得到该部分文档,而是一个完整的文档,例如,包含隐含元素。幸运的是,实际系统是在一个完整的HTML文档上运行的。谢谢,伙计!@Kokos尝试使用
$dom->encoding='utf-8'
。如果这没有帮助,请使用
utf8\u encode
调用ba签入。如果这对尝试使用
iconv
没有帮助,请检查您的服务器头。元元素是回退元素。如果您的服务器发送编码头,则永远不会拾取元。嗯,实际上我只是没有删除
utf8\u encode()
在所有地方,我都忘记了一些>.>。谢谢大家,如果我再次遇到编码问题,@Gordon我会记住这些。感谢澄清,这实际上是因为我使用
&
字符来定义被数据库信息替换的字段,如:
&&&field&&&
。幸运的是这些错误可能会感到惊讶:)嘿,哈克雷,你的思维过程是+1,但这对我来说不起作用,因为该系统是电子邮件营销系统的一部分。出于这个原因,我无法使用样式表,这也是我必须检查内联样式标记和排序的原因。啊,好的,当然,那么你需要对样式进行编码。疯帽子样式。雷恩ch那些html块,炸掉那些坏掉的html电子邮件客户端;)很好。但是请记住,当您使用
saveXml
时,您将获得与XML兼容的输出,例如,
而不是

。尽管我完全同意所有html都是标记汤,但应该指出区别。是的,对。特别是关于用于HTML的片段。我应该检查
saveHTML()
是否可以解决这个问题。
<!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>
// get html fragment
$output = implode('', array_map(
  function($node) use ($dom) { return $dom->saveXml($node); },
  iterator_to_array($xpath->query('//body/*'), false)))
  ;
// get html fragment
$output = '';
foreach($xpath->query('//body/*') as $node) 
  $output .= $dom->saveXml($node)
  ;