PHP Regex preg_match_all div不是同一个id

时间:2014-06-18 01:08:10

标签: php jquery html css regex

我有一个像这样的HTML页面

<!DOCTYPE html>
    <html>
        ....
        <body>
            <div class="list-news fl pt10 ">
                Blue
            </div>
            <div class="list-news fl pt10 alternative">
                Yellow
            </div>
             <div class="list-news fl pt10 ">
                Red
            </div>
            <div class="list-news fl pt10 alternative">
                Cyan
            </div>
            <div class="list-news fl pt10 ">
                Black
            </div>
            <div class="list-news fl pt10 alternative">
                White
            </div>
        </body>
    </html>

现在我将编写一个PHP代码来获取我需要的所有内容

preg_match_all('@<div class="list-news fl pt10 .*?">(.*?)<div class="list-news fl pt10 .*?">@s',$rs,$match);

现在这是结果

[1] => Array
(
    [0] => <div>Blue</div></div>
    [1] => <div>Red</div></div>
    [2] => <div>Black</div></div>
)

结果只显示div <div class="list-news fl pt10 ">中的内容而不是<div class="list-news fl pt10 alternative">中的内容我可以使用str_replace删除alternative类但如果不替换此字符串,怎么能得到每个div匹配类list-news fl pt10.*?中的所有内容?

感谢您的想法。

1 个答案:

答案 0 :(得分:4)

DOM方式(带有幼稚contains

$dom = new DOMDocument();
@$dom->loadHTML($html);

$xpath = new DOMXPath($dom);

$query = <<<'EOD'
//div[
    contains(@class, 'list-news') and
    contains(@class, 'fl') and
    contains(@class, 'pt10')]
EOD;

$nodes = $xpath->query($query);

$results = array();

foreach ($nodes as $node) {
    $results[] = trim($node->textContent);

}
print_r($results);

正则表达式方法(带有天真模式)

preg_match_all('~<div class="list-news fl pt10\b[^>]+>\s*\K.*?(?=\s*</div>)~',
               $html, $matches);
print_r($matches[0]);

这两种方式有点幼稚,因为contains并不关心单词边界和类顺序,而正则表达式模式并不关心html代码可能存在的不规则性。 / p>

您的模式不起作用的原因是您无法获得重叠匹配。由于第一次出现以<div class="list-news...结尾,因此下一次出现不能以已经匹配的相同<div class="list-news...开头。

将最后一个<div class="list-news...置于先行(?=...) (这只是一个检查,而内容不是匹配结果的一部分)可以是一种方式。但是,使用结束标记</div>更简单。

\K用于从匹配结果中删除(左侧)之前匹配的所有内容。

一个很好的折衷方案是提取包含class属性的所有div标签,然后在提取和修剪文本内容之前检查属性值是否真正符合正则表达式:

$dom = new DOMDocument();
@$dom->loadHTML($html);

$xpath = new DOMXPath($dom);

$query = '//div[@class]';

$nodes = $xpath->query($query);

$results = array();

foreach($nodes as $node) {
    if ( preg_match('~(?:\s|^)list-news\s+fl\s+pt10(?:\s|$)~',
                    $node->getAttribute('class')) )
        $results = trim($node->textContent);
}

或没有XPath

$dom = new DOMDocument();
@$dom->loadHTML($html);

$divs = $dom->getElementsByTagName('div');

$results = array();

foreach($divs as $node) {
    if ( $node->hasAttribute('class') &&
         preg_match('~(?:\s|^)list-news\s+fl\s+pt10(?:\s|$)~',
                    $node->getAttribute('class')) )
        $results = trim($node->textContent);
}