PHP-парсер PHP, который позволяет мне делать выбор класса и получать родительские узлы

Таким образом, я в ситуации, когда я очищаю веб-сайт с PHP, и мне нужно иметь возможность получить узел на основе его класса css. Мне нужно получить тег ul, который не имеет атрибута id, но имеет класс css. Затем мне нужно получить только теги li, которые содержат определенные теги привязки, а не все теги li.

Я просмотрел DOMDocument, Zend_Dom, и у меня нет обоих требований, выбора класса и обхода объекта (в частности, восхождение к родителям).

Solutions Collecting From Web of "PHP-парсер PHP, который позволяет мне делать выбор класса и получать родительские узлы"

Вы можете использовать querypath, и тогда что-то вроде этого может работать:

htmlqp($html)->find("ul.class")->not("#id") ->find('li a[href*="specific"]')->parent() // then foreach over it or use ->writeHTML() for extraction 

См. http://api.querypath.org/docs/class_query_path.html для API.

(Перемещение намного проще, если вы не используете Fiddly DOMDocument.)

Вы можете сделать это с помощью DOMDocument и DOMXPath . Выбор по классу в XPath – это боль, но это можно сделать.

Вот пример (и полностью действительный!) HTML:

 $html = <<<EOT <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <title>Document Title</title> <ul id="myid"><li>myid-listitem1</ul> <ul class="foo theclass "><li>list2-item1<li>list2-item2</ul> <ul id="myid2" class="foo&#xD;theclass bar"><li>list3-item1<li>list3-item2</ul> EOT ; $doc = new DOMDocument(); $doc->loadHTML($html); $xp = new DOMXPath($doc); $nodes = $xp->query("/html/body//ul[not(@id) and contains(concat(' ',normalize-space(@class),' '), ' theclass ')]"); var_dump($nodes->length); 

Если вы используете PHP 5.3, вы можете упростить это, зарегистрировав функцию XPath в php. (Обратите внимание, что вы можете регистрировать функции для использования в выражениях XPath с помощью XSLTProcessor начиная с PHP 5.1, но не напрямую для DOMXPath .)

 function hasToken($nodearray, $token) { foreach ($nodearray as $node) { if ($node->nodeValue===null or !hasTokenS($node->nodeValue, $token)) { return False; } } return True; // I could even return nodes or document fragments if I wanted! } function hasTokenS($str, $token) { $str = trim($str, "\r\n\t "); $tokens = preg_split('/[\r\n\t ]+/', $str); return in_array($token, $tokens); } $xp->registerNamespace('php', 'http://php.net/xpath'); $xp->registerPhpFunctions(array('hasToken', 'hasTokenS')); // These two are equivalent: $nodes1 = $xp->query("/html/body//ul[not(@id) and php:function('hasToken', @class, 'theclass')]"); $nodes2 = $xp->query("/html/body//ul[not(@id) and php:functionString('hasTokenS', @class, 'theclass')]"); var_dump($nodes1->length); var_dump($nodes1->item(0)); var_dump($nodes2->length); var_dump($nodes2->item(0)); 

Если DOMDocument просто не DOMDocument ваш HTML очень хорошо, вы можете использовать парсер html5lib , который вернет DOMDocument:

 require_once('lib/HTML5/Parser.php'); // or where-ever you put it $dom = HTML5_Parser::parse($html); // $dom is a plain DOMDocument object, created according to html5 parsing rules 

Мне повезло: http://simplehtmldom.sourceforge.net/