我有HTML (由第三方应用程序生成),我需要清理和修改各种方式。我需要做的一件事是将嵌套在包含其他文本和元素的P元素中的IMG元素移动到它们自己的段落中。我知道PHP DOM扩展,并将其用于某些用途,但对于此操作,最好使用正则表达式。在包含IMG元素的P之前可能有零个或多个P元素,IMG元素在嵌套P元素内可以在它之前或之后具有任何元素或文本,并且可能有一个以上的IMG元素嵌套在单个P中。例如,我想转换
<p>Gah1</p><p>Blah1<img src="blah.jpg"/> Blah2</p><p>Gah2</p>至
<p>Gah1</p><p><img src="blah.jpg"/></p><p>Blah1 Blah2</p><p>Gah2</p> 我试过了:
preg_replace("/<p>(.*?)(<img\s+[^>]*\/>)(.*?)<\/p>/is", "<p>$2</p><p>$1$3</p>", $input);但这会将IMG元素放在开头(因为我猜不情愿的第一组仍然从字符串的开头开始):
<p><img src="blah.jpg"/></p><p>Gah1</p><p>Blah1 Blah2</p><p>Gah2</p>而且它也只能处理每个段落中的一个图像。我也尝试过各种(负面的)look-ahead的组合,但也不能让它们工作。帮助!
发布于 2015-05-07 07:41:25
因此,我最终使用了多个正则表达式和迭代,而不是试图使用单个正则表达式来实现这一点:
// Check if there are any paragraphs containing images first.
if (preg_match('/<p[^>]*>.*?<img\s+[^>]*\/>.*?<\/p>/is', $input)) {
// Get individual paragraphs.
$paragraphs = array();
preg_match_all('/<p[^>]*>.*?<\/p>/is', $input, $paragraphs);
foreach ($paragraphs[0] as $para) {
$images = array();
if (preg_match_all('/<img\s+[^>]*\/>/is', $para, $images)) {
// Strip images from this paragraph.
$new_paras = preg_replace('/<img\s+[^>]*\/>/is', '', $para);
// We put the images under the paragraph they were anchored in because they tend to
// be anchored in the paragraph they're visually positioned in or the one above.
foreach ($images[0] as $img) {
$new_paras .= "<p>$img</p>";
}
// Replace existing paragraph containing images.
$input = str_replace($para, $new_paras, $input);
}
}
}在此过程中,我尝试使用PHPs DOM扩展,发现它非常麻烦和困难,因为以前获得的对元素的引用在其他元素被修改或插入时变得混乱(尽管我仍然使用它来清理和解析原始HTML )。我还发现,在正则表达式中使用负前视或-behind来避免匹配多个段落会导致内存不足错误(输入字符串可能非常长),因此在上面的代码中首先将输入分解为单个段落。
https://stackoverflow.com/questions/30043429
复制相似问题