我想在字符串中找到不在<pre>
标记中的注释标记,并将它们包装在<pre>
标记中。
似乎没有办法使用PHP DOM来"查找"注释。
我已经在使用regex进行一些处理了,但我对regex中的前向和后向非常不熟悉(尚未掌握或真正理解)。
例如,我可能有以下代码;
<!-- Comment 1 -->
<pre>
<div class="some_html"></div>
<!-- Comment 2 -->
</pre>
我想将Comment 1包装在<pre>
标记中,但显然不包装Comment 2,因为它已经驻留在<pre>
中。
在RegEx中通常是如何做到这一点的?
以下是我对消极环视的理解,以及我的尝试,我显然做错了什么!
(?<!<pre>.*?)<!--.*-->(?!.*?</pre>)
如果您计划重新使用此代码,那么您确实应该使用DOM解析器。当使用真实世界的HTML时,每种regex方法都会很快失败。
话虽如此,以下是你可以(但不应该,见上文)做的:
首先,识别评论,例如使用
<!-- (?:(?!-->).)*-->
负先行块可确保.*不会用完注释块。
现在,您需要弄清楚这个注释是否在<pre>
块中。这里的关键观察结果是,每个注释后面都有偶数个<pre>
或</pre>
元素,而这些元素还没有包含在一个注释中。
因此,请始终以<pre>
为一对,遍历文本的其余部分,并检查是否到达末尾。
这看起来像
(?=(?:(?!</?pre>).)*(?:</?pre>(?:(?!</?pre>).)*</?pre>(?:(?!</?pre>).)*)*$)
所以,这就是
<!-- (?:(?!-->).)*-->(?=(?:(?!</?pre>).)*(?:</?pre>(?:(?!</?pre>).)*</?pre>(?:(?!</?pre>).)*)*$)
只写代码的欢呼=)
该表达式的突出构建块是(?:(?!</?pre>).)
,它匹配不是<pre>
或</pre>
序列的起始括号的每个字符。
允许<pre>
上的属性和正确的转义留给读者练习。请参阅RegExr中的操作。
似乎没有办法使用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*-->
。。。在这里试试
编辑:
只是一个关于后备的注意事项,它必须有一个固定的宽度,因此你不能使用重复*+
或可选项目?
坏消息是,大多数正则表达式风格不允许在lookbacking中只使用任何正则表达式,因为它们不能向后应用正则表达式。因此,正则表达式引擎需要能够计算出在检查查找表之前需要后退多少步。
因此,许多regex风格,包括Perl和Python使用的那些风格,只允许固定长度的字符串。您可以使用任何可以预先确定匹配长度的正则表达式。这意味着您可以使用文字和字符类。不能使用重复项或可选项。可以使用交替,但前提是交替中的所有选项都具有相同的长度。
来源:http://www.regular-expressions.info/lookaround.html
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);
}
这很容易,使用一个称为堆栈计数器的原理,
本质上是计算<pre>
标签的数量和</pre>
标签的数量,直到您的片段位于HTML代码中
如果<pre>
比</pre>
多,则表示"<pre>..--you are here--..</pre>
"
在这种情况下,只需返回匹配项,未修改-就这么简单。