如何用正则表达式解析第一级嵌套标签?

时间:2012-11-16 20:25:04

标签: php regex

说我有一个像这样的文本块:

<item>
   foo bar foo bar 
   <item> child item </item>
</item>
<item>
   second item
   <item> second child </item>
</item>

在这里,我想要的只是解析要解析的<item>的两个顶级,并将结果返回给我,如下所示:

[0] = "foo bar foo bar  <item>child item</item>"
[1] = "second item  <item>second child </item>";

然而,在我的测试中,由于子级别<item>标签与模式匹配,因此它们也包含在内,我得到一个4元素数组,而不是我想要的2元素数组。

这是我用过的模式:

%<item>(.+)</item>%si

有什么想法吗?

编辑:这不适用于HTML,它是一种自定义的内部脚本语言,我无法使用任何dom解析器。所以请建议使用正则表达式解决方案。

3 个答案:

答案 0 :(得分:2)

%<p>(.+?)^</p>%smi

修改

$text = "<item> foo bar foo bar <item> child item </item> </item> <item> second item <item> second child </item> </item>";
preg_match_all('%<item>(.*?<item>.*?</item>).*?</item>%si', $text, $matches);
print_r($matches[1]);

输出

Array
(
    [0] =>  foo bar foo bar <item> child item </item>
    [1] =>  second item <item> second child </item>
)

答案 1 :(得分:1)

正则表达式并不适合您正在做的事情。如果你追求这条路线,你可能会花费更多的时间,而不是你走另一条路线。我建议你查看一个DOM解析器。下面的一个相当容易使用,应该可以满足您的基本需求。

PHP Simple HTML DOM Parser

同时查看this question,因为它会为您提供更多选择。

答案 2 :(得分:0)

您说输入不是HTML,而是提供了一个看起来像HTML的字符串。请参阅,正则表达式最适用于纯文本,而不是标记文本。你没有透露这种输入背后的真实语言是什么,因此,我可以建议的解决方案是基于假设<字符不能作为文字中间元素节点出现(仅作为某个实体)。

这意味着,您可以使用否定字符类 [^<]并将*量词应用于它:

%<item>([^<]+)</item>%i

请参阅regex demoPHP demo

$text = "<item> foo bar foo bar <item> child item </item> </item> <item> second item <item> second child </item> </item>";
preg_match_all('%<item>([^<]*)<item>%i', $text, $matches);
print_r($matches[1]);
// => Array ( [0] =>  foo bar foo bar  [1] =>  second item )