嵌套Div标签的PHP RegExp [英] PHP RegExp for nested Div tags

查看:60
本文介绍了嵌套Div标签的PHP RegExp的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个正则表达式,可以与PHP的preg_match_all()配合使用,以匹配div-tags中的内容. div看起来像这样:

<div id="t1">Content</div>

到目前为止,我已经提出了这个正则表达式,它匹配了所有id ="t [number]"

的div.

/<div id="t(\\d)">(.*?)<\\/div>/

问题是,当内容包含更多div时,嵌套div如下所示:

<div id="t1">Content <div>more stuff</div></div>

关于如何使我的正则表达式与嵌套标签一起使用的任何想法?

谢谢

解决方案

请尝试使用解析器:

require_once "simple_html_dom.php";
$text = 'foo <div id="t1">Content <div>more stuff</div></div> bar <div>even more</div> baz  <div id="t2">yes</div>';
$html = str_get_html($text);
foreach($html->find('div') as $e) {
    if(isset($e->attr['id']) && preg_match('/^t\d++/', $e->attr['id'])) {
        echo $e->outertext . "\n";
    }
}

输出:

<div id="t1">Content <div>more stuff</div></div>
<div id="t2">yes</div>

在此处下载解析器: http://simplehtmldom.sourceforge.net/

出于个人喜好,我尝试在正则表达式中进行操作.这是我想出的:

$text = 'foo <div id="t1">Content <div>more stuff</div></div> bar <div>even more</div>
      baz <div id="t2">yes <div>aaa<div>bbb<div>ccc</div>bbb</div>aaa</div> </div>';
if(preg_match_all('#<div\s+id="t\d+">[^<>]*(<div[^>]*>(?:[^<>]*|(?1))*</div>)[^<>]*</div>#si', $text, $matches)) {
    print_r($matches[0]);
}

输出:

Array
(
    [0] => <div id="t1">Content <div>more stuff</div></div>
    [1] => <div id="t2">yes <div>aaa<div>bbb<div>ccc</div>bbb</div>aaa</div> </div>
)

还有一个简短的解释:

<div\s+id="t\d+">  # match an opening 'div' with an id that starts with 't' and some digits
[^<>]*             # match zero or more chars other than '<' and '>'
(                  # open group 1
  <div[^>]*>       #   match an opening 'div'
  (?:              #   open a non-matching group
    [^<>]*         #     match zero or more chars other than '<' and '>'
    |              #     OR
    (?1)           #     recursively match what is defined by group 1
  )*               #   close the non-matching group and repeat it zero or more times
  </div>           #   match a closing 'div'
)                  # close group 1
[^<>]*             # match zero or more chars other than '<' and '>'
</div>             # match a closing 'div'

现在也许您已经理解为什么人们尝试使用正则表达式来说服您 not .如前所述,如果html的格式不正确,这将无济于事:我向您保证,正则表达式会比html解析器产生更大的输出混乱.另外,正则表达式可能会使您流血,并且您的同事(或维护您软件的人员)可能会在看到您的所作所为之后找您. :)

您最好的选择是先清理您的输入(使用 TIDY 或类似的方法),然后使用解析器获取所需的信息.

I need a regexp I can use with PHP's preg_match_all() to match out content inside div-tags. The divs look like this:

<div id="t1">Content</div>

I've come up with this regexp so far which matches out all divs with id="t[number]"

/<div id="t(\\d)">(.*?)<\\/div>/

The problem is when the content consists of more divs, nested divs like this:

<div id="t1">Content <div>more stuff</div></div>

Any ideas on how I make my regexp work with nested tags?

Thanks

解决方案

Try a parser instead:

require_once "simple_html_dom.php";
$text = 'foo <div id="t1">Content <div>more stuff</div></div> bar <div>even more</div> baz  <div id="t2">yes</div>';
$html = str_get_html($text);
foreach($html->find('div') as $e) {
    if(isset($e->attr['id']) && preg_match('/^t\d++/', $e->attr['id'])) {
        echo $e->outertext . "\n";
    }
}

Output:

<div id="t1">Content <div>more stuff</div></div>
<div id="t2">yes</div>

Download the parser here: http://simplehtmldom.sourceforge.net/

Edit: More for my own amusement I tried to do it in regex. Here's what I came up with:

$text = 'foo <div id="t1">Content <div>more stuff</div></div> bar <div>even more</div>
      baz <div id="t2">yes <div>aaa<div>bbb<div>ccc</div>bbb</div>aaa</div> </div>';
if(preg_match_all('#<div\s+id="t\d+">[^<>]*(<div[^>]*>(?:[^<>]*|(?1))*</div>)[^<>]*</div>#si', $text, $matches)) {
    print_r($matches[0]);
}

Output:

Array
(
    [0] => <div id="t1">Content <div>more stuff</div></div>
    [1] => <div id="t2">yes <div>aaa<div>bbb<div>ccc</div>bbb</div>aaa</div> </div>
)

And a small explanation:

<div\s+id="t\d+">  # match an opening 'div' with an id that starts with 't' and some digits
[^<>]*             # match zero or more chars other than '<' and '>'
(                  # open group 1
  <div[^>]*>       #   match an opening 'div'
  (?:              #   open a non-matching group
    [^<>]*         #     match zero or more chars other than '<' and '>'
    |              #     OR
    (?1)           #     recursively match what is defined by group 1
  )*               #   close the non-matching group and repeat it zero or more times
  </div>           #   match a closing 'div'
)                  # close group 1
[^<>]*             # match zero or more chars other than '<' and '>'
</div>             # match a closing 'div'

Now perhaps you understand why people try to persuade you from not using regex for this. As already noted, it will not help if the the html is improperly formed: the regex will make a bigger mess of the output than an html parser, I assure you. Also, the regex will probably make your eyes bleed and your colleagues (or the people who will maintain your software) may come looking for you after seeing what you did. :)

Your best bet is to first clean up your input (using TIDY or similar), and then use a parser to get the info you want.

这篇关于嵌套Div标签的PHP RegExp的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆