php - preg 匹配标签之间的文本,排除之间的相同标签

标签 php html regex tags pcre

好吧,我知道有几个类似的问题,但在这个特定案例中找不到任何问题。

我使用了一段代码并根据需要对其进行了调整,但现在我在其中发现了一个我无法纠正的错误。

代码:

$tag = 'namespace';
$match = Tags::get($f, $tag);
var_dump($match); 

  static function get( $xml, $tag) { // http://stackoverflow.com/questions/3404433/get-content-within-a-html-tag-using-7-processing
// bug case      string(56) "<namespaces>
//      <namespace key="-2">Media</namespace>"
      $tag_ini = "<{$tag}[^\>]*?>"; $tag_end = "<\\/{$tag}>";
      $tag_regex = '/' . $tag_ini . '(.*?)' . $tag_end . '/si';

      preg_match_all($tag_regex,
      $xml,
      $matches,
      PREG_OFFSET_CAPTURE);
      return $matches;
  }

如你所见,如果标签是嵌套的,就会出现错误:

<namespaces> <namespace key="-2">Media</namespace>

什么时候应该返回'Media',甚至是外层的'<namespaces>'然后是里面的。

我尝试添加“<{$tag}[^\>|^\r\n ]*?>”,^\s+ ,将 * 更改为 *?,以及其他一些在最好的情况下只能识别错误情况的事情。

也试过"<{$tag}[^{$tag}]*?>"这给出了空白,我想它会自行无效。

我是正则表达式的新手,我可以说要解决这个问题只需要添加不要让打开相同类型的新标签。 或者我什至可以为我的用例使用 hack 答案,排除内部文本是否有换行符。

谁能得到正确的语法?


您可以在此处查看文本摘录:http://pastebin.com/f2naN2S3


提议的更改后:$tag_ini = "<{$tag}\\b[^>]*>"; $tag_end = "<\\/{$tag}>";它确实适用于示例案例,但不适用于此案例:

<namespace key="0" />
      <namespace key="1">Talk</namespace>

因为它导致:

<namespace key="1">Talk"

这是因为数字和 "以及字母被认为是在单词边界内。我该如何解决这个问题?

最佳答案

主要问题是您没有在开始标记后使用单词边界,因此,namespace在模式中也可以匹配 namespaces标记和许多其他标记。

后续问题是 <${tag}\b[^>]*>(.*?)<\/${tag}>如果有一个自动关闭模式会过火 namespace标签后跟“正常”成对打开/关闭 namespace标签。因此,您需要使用负面回顾 (?<!\/)> 之前(参见 demo ),或使用 (?![^>]*\/>) \b 之后的负前瞻(参见 demo)。

所以,你可以使用

$tag_ini = "<{$tag}\\b[^>]*(?<!\\/)>"; $tag_end = "<\\/{$tag}>";

关于php - preg 匹配标签之间的文本,排除之间的相同标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37512370/

相关文章:

php - Phalcon 持久型

php - 使用 php 在标签内查找名称属性

java - 尝试为字母数字字符串编写正则表达式,例如 - R51/53

html - SASS/Flexbox 不工作

javascript - 正则表达式允许任何字符,但需要使用javascript接受整个文本框的单个空格

javascript - 正则表达式: Match word or Phrase

php - 在 PHP 中更新图像类别时出错

php - 我可以在 laravel 查询生成器中同时使用 `join` 和 `with` 吗?

php - 在 symfony 4 中使用未定义的常量 XML_PI_NODE

html - 垂直菜单,鼠标悬停时子菜单会飞出