Вы можете сделать это с помощью 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
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
просто не очень хорошо разбирает ваш 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