PHP在字符串中获取html注释并包装在<pre> tag. Regex or DOM?</pre>中

时间:2013-08-16 09:02:12

标签: php regex html

我想在字符串中找到尚未在<pre>标记内的评论标记,并将其包装在<pre>标记中。

似乎没有办法找到&#39;使用PHP DOM的评论。

我已经使用正则表达式进行了一些处理,但是我非常不熟悉(尚未掌握或真正理解)展望未来并在正则表达式中看后面。

例如,我可能有以下代码;

<!-- Comment 1 -->

<pre>
    <div class="some_html"></div>
    <!-- Comment 2 -->
</pre>

我想在<pre>代码中包含评论1,但显然不是评论2,因为它已经位于<pre>

这通常如何在RegEx中完成?

这是我对负面看法的理解,以及我对其中的一种尝试,我显然做了一些非常错误的事情!

(?<!<pre>.*?)<!--.*-->(?!.*?</pre>)

4 个答案:

答案 0 :(得分:2)

如果您计划重新使用此代码,则应该使用DOM解析器。当呈现真实世界的HTML时,每个正则表达式方法都会很快失败。

话虽如此,这是你能做的(但不应该,见上文):

首先,确定评论,例如使用

<!-- (?:(?!-->).)*-->

负向预测块确保。*不会用完注释块。

现在,您需要确定此评论是否在<pre>块内。这里的关键观察是,每个评论之后的<pre></pre>元素都是偶数个。

因此,请仔细检查文本的其余部分,并始终成对<pre>,并检查是否到达最后。

这看起来像

(?=(?:(?!</?pre>).)*(?:</?pre>(?:(?!</?pre>).)*</?pre>(?:(?!</?pre>).)*)*$)

所以,这将是

<!-- (?:(?!-->).)*-->(?=(?:(?!</?pre>).)*(?:</?pre>(?:(?!</?pre>).)*</?pre>(?:(?!</?pre>).)*)*$)

只写代码的欢呼=)

此表达式的突出构建块是(?:(?!</?pre>).),它匹配的每个字符都不是<pre></pre>序列的起始括号。

允许<pre>上的属性和正确的转义留给读者练习。请在RegExr处查看此操作。

答案 1 :(得分:1)

  

似乎没有办法使用PHP DOM“查找”评论。

当然你可以......使用PHP Simple HTML DOM Parser检查此代码:

<?php
$text = '<!-- Comment 1 -->

        <pre>
            <div class="some_html"></div>
            <!-- Comment 2 -->
        </pre>';

echo  "<div>Original Text: <xmp>$text</xmp></div>";

$html = str_get_html($text);

$comments = $html->find('comment');

// if find exists
if ($comments) {

  echo '<br>Find function found '. count($comments) . ' results: ';

  foreach($comments as $key=>$com){
    echo '<br>'.$key . ': ' . $com->tag . ' wich contains = <xmp>' . $com->innertext . '</xmp>';
  }
}
else
  echo "Find() fails !";
?>

$com->innertext会为您提供<!-- Comment 1 --> ...

等评论

您现在只需按照自己的意愿清洁它们。例如,使用<!--\s*(.*)\s*--> ...尝试HERE

编辑:

只是关于lookbehind的注释,它必须有固定宽度,因此你不能使用重复*+或可选项?

  

坏消息是大多数正则表达式都不允许你在lookbehind中使用任何正则表达式,因为它们不能向后应用正则表达式。因此,正则表达式引擎需要能够在检查lookbehind之前找出退回的步骤数。

     

因此,许多正则表达式,包括Perl和Python使用的那些,只允许固定长度的字符串。您可以使用任何可以预先确定匹配长度的正则表达式。这意味着您可以使用文字文本和字符类。您不能使用重复或可选项。您可以使用交替,但仅当交替中的所有选项具有相同的长度时才会使用。

     

来源:http://www.regular-expressions.info/lookaround.html

答案 2 :(得分:0)

Xpath是你的朋友:

$xpath = new DOMXpath($doc);

foreach($xpath->query('//comment()[not(ancestor::pre)]') as $comment){
  $pre = $doc->createElement("pre");
  $comment->parentNode->insertBefore($pre, $comment);
  $pre->appendChild($comment);
}

答案 3 :(得分:0)

它很容易,使用一个称为堆栈计数器的原则,基本上你计算<pre>标签的数量和</pre>标签的数量,直到HTML代码中的点为止细分市场。
如果更多 <pre>而不是</pre> - 这意味着“<pre>..--you are here--..</pre>”。
在这种情况下,只需返回比赛,未经修改 - 就这么简单。