【问题标题】:A regular expression to extract text between two tags and ALSO the tag name用于在两个标签之间提取文本的正则表达式以及标签名称
【发布时间】:2010-07-09 01:40:19
【问题描述】:

我需要一种简单的标记语言来将字符串的不同部分存储在 TEXT 字段中,然后提取这些部分。 所以基本上我想要某种简单的 XML。将它们存储在表字段中很容易,但提取它们......是另一回事。 我设法使用为常规 HTML 完成的简单正则表达式来做到这一点:

|<[^>]+>(.*)</[^>]+>|U

但为了重新组合原始数组(并更普遍地使用标记),我还需要知道标签名称。而那个正则表达式并没有这样做。

例子:

输入文字:

<user_input>Hello! my name is Williams</user_input>

使用上述正则表达式的 preg_match_all() 函数返回:

array
  0 => 
    array
      0 => string '<user_input>Hello! my name is Williams</user_input>' (length=34)

  1 => 
    array
      0 => string 'Hello! my name is Williams' (length=34)

我需要它来返回标签的“user_input”名称。是的,我知道,我很喜欢正则表达式。是的,我知道“使用 XML 解析器”,但这对于我正在做的事情来说太大了。

【问题讨论】:

  • 你的正则表达式是贪婪的,任何复杂的东西都会严重破坏。它不检查标签是否匹配。如果有两个以上的标签,它将非常失败。我确定它还有其他错误。
  • “所以基本上我想要某种简单的 XML。”——恰好 PHP 带有一个名为 SimpleXML 的扩展:php.net/simplexml

标签: php xml regex


【解决方案1】:

xml 解析器如何“太大”? PHP 具有内置的本机函数,可让您轻松完成。

正则表达式不适合这项工作。

<?php

$string = '
<root>
<input_name>blah</input_name>
</root>
';

$x = new DOMDocument();
$x->loadXML($string);
$root = $x->documentElement;
$elements = $root->getElementsByTagName('*');
$count = count($elements->length);

for ( $i = 0; $i< $count; $i++ ) {
    $el = $elements->item($i);
    echo $el->nodeName . '<br>';
    echo $el->nodeValue . '<br>';
}

【讨论】:

  • 你也可以使用simplexml。
【解决方案2】:

只需像处理内容一样使用捕获组:

|<([^>]+)>([^<]*)</\1>|

作为额外的奖励,您可以使用捕获的名称来确保结束标记具有相同的名称。

【讨论】:

    【解决方案3】:

    所以基本上我想要某种简单的 XML

    那么你需要一个 XML 解析器。嘿,PHP 有一个你可以安装的 XML 解析扩展。

    说真的,试图用正则表达式破解你的方式只会以痛苦和沮丧而告终。使用 XML 解析器,为您节省大量工作时间。

    但这对于我正在做的事情来说太大了。

    不,不是。您想要解析一些东西 - 因此,您应该使用解析器。

    【讨论】:

    • 人们在不发表评论的情况下投反对票很有趣。你失去了代表,答案没有改善 - 你到底取得了什么成就?
    • 我推荐使用 xml 解析器,但是如何提供一个使用它来解决操作问题的示例?这将帮助他理解它是如何工作的,而不是“RTFM”类型的响应。
    • @meder:我不是一个 PHP 专家——为了发布一个工作代码示例,我必须安装 PHP,正确配置所有内容,并多次测试我的代码确保它有效。我更愿意发布一个有用的答案,将提问者指向正确的方向,即使它在可复制粘贴的代码上很简洁。也就是说,你的答案比我的好,我赞成它是正确的并提供了示例用法。
    • 解析器是一个不错的解决方案,但我已经完成了正则表达式的代码(不仅仅是解析字符串的方法,还有围绕它的代码)。如果用户数量增加并且我在扩展方面遇到了一些问题,我可能会重构它以使用解析器。无论如何,谢谢,我学到了一个可能会在未来使用的新东西。
    【解决方案4】:
    |<([^>]+)>(.*)</[^>]+>|U
    

    会做你想做的。我只是添加了两个括号。这是一个非常脆弱的黑客。您想使用解析器。尤其是你显然不懂正则表达式。

    【讨论】:

      最近更新 更多