Стиль неизученных связей с DOM и xpath

Для системы, которую я LINKSTYLE , я определяю общий style хранящийся в LINKSTYLE который должен применяться к элементам, которые еще не разработаны (встроены). Я не очень DOMDocument в 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; 

С помощью этого обновленного кода я не получаю больше ошибок, однако элемент не получает стилей.

Используйте libxml_use_internal_errors(true) чтобы подавить ошибки синтаксического анализа, связанные с loadHTML .

  • libxml_use_internal_errors() – Отключить ошибки libxml и разрешить пользователю получать информацию об ошибке

Запрос XPath недействителен, поскольку contains ожидаемое значение в атрибуте style.

  • 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.

Первая ошибка (до редактирования) возникает, когда вы используете внутренний документ a & для других целей, чем создание ссылки на сущность (например &quot; ).

Обычно это происходит в URL-адресах, когда вы делите GET-параметры.

Вы можете игнорировать эти ошибки с помощью предложения Гордона или исправить его (замените вхождения & by &amp; ).

Мне было интересно, можно ли разрешить это более 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

И чтобы получить измененный фрагмент 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) ;