Php 如何使用正则表达式仅解析第一级嵌套标记?

Php 如何使用正则表达式仅解析第一级嵌套标记?,php,regex,Php,Regex,假设我有一块这样的文本: <item> foo bar foo bar <item> child item </item> </item> <item> second item <item> second child </item> </item> [0] = "foo bar foo bar <item>child item</item>" [1

假设我有一块这样的文本:

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

福吧福吧
子项
第二项
第二胎
这里,我只想解析要解析的
的两个顶层,结果以如下数组返回给我:

<item>
   foo bar foo bar 
   <item> child item </item>
</item>
<item>
   second item
   <item> second child </item>
</item>
[0] = "foo bar foo bar  <item>child item</item>"
[1] = "second item  <item>second child </item>";
[0]=“foo-bar foo-bar子项”
[1] =“第二项第二子项”;
然而,在我的测试中,由于子级
标记与模式匹配,因此它们也包括在内,我得到了一个4元素数组,而不是我想要的2元素数组

这是我使用的模式:

%<item>(.+)</item>%si
%(.+)%si
有什么想法吗


Edit:这不是针对HTML的,它是针对一种自定义的内部脚本语言,我不能使用任何dom解析器。因此,请推荐一种正则表达式解决方案。

正则表达式并不适合您所做的工作。如果你沿着这条路走,你可能会花更多的时间在上面,而不是走另一条路。我建议您检查DOM解析器。下面的一个很容易使用,应该可以满足您的基本需求

还可以查看,因为它将为您提供其他选择。

%(.+?)^

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

$text=“foo-bar foo-bar子项第二项第二子项”;
preg_match_all('%(.*?*?).*?%si',$text,$matches);
打印($matches[1]);
输出

Array
(
    [0] =>  foo bar foo bar <item> child item </item>
    [1] =>  second item <item> second child </item>
)
数组
(
[0]=>foo-bar foo-bar子项
[1] =>第二项第二个子项
)

您说输入不是HTML,而是提供了一个类似HTML的字符串。请参阅,正则表达式最适用于纯文本,而不是标记文本。您无法揭示这类输入背后的真正语言,因此,我可以建议的解决方案基于这样一种假设,即
数组([0]=>foo-bar foo-bar[1]=>第二项)

这不是针对HTML的,它是针对自定义脚本语言的,我不能使用任何DOM解析器。你能发布一个该自定义语言完整部分的真实示例吗?这与这个问题无关。我已经发布了与我需要做的事情相关的内容。它是有效的,但是如果我将行移动到同一行上,例如,然后它停止工作。你继续移动goalpost:PIf我在一个main
中放入了多个嵌套的
标记,然后它再次失败。这里的真正答案是不使用正则表达式来查看html。有一些html解析器可以使这变得更容易,也更不容易出错。这不是针对html的,它是针对自定义脚本语言的,我不能使用任何DOM解析器。“自定义脚本语言”是什么意思。你是说这些不是段落HTML元素标记吗?@jeroen这是脚本语言中唯一的一块文本,允许非技术用户指定一些规则。它是定制的。我已经尝试过了,但无法使用任何dom解析器。我需要通过正则表达式来实现这一点。@jeroen不幸的是,它不是结构化的XML,正如您从示例中看到的那样
$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 )