我在处理文本内容中的HTML方面遇到了麻烦。我正在考虑一种检测这些标记的方法,并将所有连续的标记包装在代码标记内。
不要包裹我<p>Hello</p><div class="text">wrap me please!</div><span class="title">wrap me either!</span>
不要包裹我<h1>End</h1>
。
//预期结果
不要包裹我<code><p>Hello</p><div class="text">wrap me please!</div><span class="title">wrap me either!</span></code>
不要包裹我<code><h1>End</h1></code>
。
这可能吗?
答案 0 :(得分:4)
在这种特定情况下很难使用DOMDocument,因为它自动包装带有<p>
标签的文本节点(并添加doctype,head,html)。一种方法是使用(?(DEFINE)...)
特性和命名子模式将模式构造为词法分析器:
$html = <<<EOD
Don't wrap me<p>Hello</p><div class="text">wrap me please!</div><span class="title">wrap me either!</span> Don't wrap me <h1>End</h1>
EOD;
$pattern = <<<'EOD'
~
(?(DEFINE)
(?<self> < [^\W_]++ [^>]* > )
(?<comment> <!-- (?>[^-]++|-(?!->))* -->)
(?<cdata> \Q<![CDATA[\E (?>[^]]++|](?!]>))* ]]> )
(?<text> [^<]++ )
(?<tag>
< ([^\W_]++) [^>]* >
(?> \g<text> | \g<tag> | \g<self> | \g<comment> | \g<cdata> )*
</ \g{-1} >
)
)
# main pattern
(?: \g<tag> | \g<self> | \g<comment> | \g<cdata> )+
~x
EOD;
$html = preg_replace($pattern, '<code>$0</code>', $html);
echo htmlspecialchars($html);
(?(DEFINE)..)
功能允许将定义部分放在正则表达式模式中。这个定义部分和里面的命名子模式没有任何匹配,它们将在稍后的主模式中使用。
(?<abcd> ...)
定义了一个子模式,您稍后可以使用\g<abcd>
重复使用该子模式。在上面的模式中,以这种方式定义的子模式是:
<强>自强>:
[^\W_]
是获取\w
而没有下划线的技巧。 [^\W]++
代表标记名称,也在tag
子模式中使用
[^>]*
表示所有不是>
零次或多次。
<强>注释强>:
(?>[^-]++|-(?!->))*
描述了html评论中的所有可能内容:
(?> # open an atomic group
[^-]++ # all that is not a literal -, one or more times (possessive)
| # OR
- # a literal -
(?!->) # not followed by -> (negative lookahead)
)* # close and repeat the group zero or more times
<强> CDATA 强>:
\Q..\E
之间的所有字符都被视为文字字符,[
之类的特殊字符不需要转义。 (这只是使图案更具可读性的技巧)。
CDATA中允许的内容的描述方式与html注释中的内容相同。
文字:
[^<]++
所有字符,直到打开尖括号或字符串结尾。
标记:
这是最有趣的子模式。第1行和第3行是开始和结束标记。请注意,在第1行中,使用捕获组捕获标记名称。在第3行中,\g{-1}
指的是最后定义的捕获组匹配的内容(&#34; -1&#34;表示&#34;左边一个&#34;)。图2描述了开始标记和结束标记之间的可能内容。您可以看到此描述不仅使用之前定义的子模式,而且使用当前子模式本身来允许嵌套标记。
设置完所有项目并关闭定义部分后,您可以轻松编写主模式。
答案 1 :(得分:0)
我在处理文本内容中的HTML方面遇到了麻烦。
然后只是逃避那个文字:
echo htmlspecialchars($your_text_that_may_contain_html_code);
使用正则表达式解析html是well-known - big- NO!
答案 2 :(得分:0)
这将找到标签及其结束标签,以及介于两者之间的所有内容:
<[A-Z][A-Z0-9]*\b[^>]*>.*?</\1>
您可以捕获这些标记并将其替换为周围的标记。它可能不适用于所有情况,但如果html是相当静态的,您可能会发现它足以满足您的需求。