我正在尝试开发一个PHP脚本,用除了具有属性的段落(例如<div id="1">
)之外的段落替换HTML字符串中的所有div。我的脚本目前所做的第一件事就是使用一个简单的str_replace()来替换所有<div>
<p>
,并留下任何带有属性和结束div标签的div标签(</div>
)。但是,将</div>
标记替换为</p>
标记会更有问题。
到目前为止,我已经开发了一个preg_replace_callback函数,用于将一些</div>
标记转换为</p>
标记以匹配开始的<p>
标记,但忽略其他</div>
}标签在结束带有属性的<div>
时。以下是我正在使用的脚本;
<?php
$input = "<div>Hello world!</div><div><div id=\"1\">How <div>are you</div> today?</div></div><div>I am fine.</div>";
$input2 = str_replace("<div>", "<p>", $input);
$output = preg_replace_callback("/(<div )|(<\/div>)/", 'replacer', $input2);
function replacer($matches){
static $count = 0;
$counter=count($matches);
for($i=0;$i<$counter;$i++){
if($matches[$i]=="<div "){
return "<div ";
$count++;
} elseif ($matches[$i]=="</div>"){
$count--;
if ($count>=0){
return "</div>";
} elseif ($count<0){
return "</p>";
$count++;
}
}
}
}
echo $output;
?>
该脚本基本上将所有剩余的<div>
和</div>
标记放入一个数组中,然后循环遍历它。然后,计数器变量在遇到<div>
标记时递增,或在遇到数组中的</div>
时递减。当计数器小于0时,返回</p>
标记,否则返回</div>
。
脚本的输出应该是;
<p>Hello world!</p><p><div id="1">How <p>are you</p> today?</div></p><p>I am fine.</p>"
相反,我得到的输出是;
<p>Hello world!</p><p><div id="1">How <p>are you</p> today?</p></p><p>I am fine.</p>
我花了几个小时对脚本进行了尽可能多的编辑,并且我不断获得相同的输出。任何人都可以向我解释我哪里出错或提供替代解决方案吗?
任何帮助都将不胜感激。
答案 0 :(得分:1)
除了mario评论的内容,与phpquery或querypath相比,您可以使用PHP DOMDocument
类来搜索有问题的<div>
元素,并将其替换为<p>
元素。< / p>
基石是DOM(文档对象模型)和XPath:
$input = "<div>Hello world!</div><div><div id=\"1\">How <div>are you</div> today?</div></div><div>I am fine.</div>";
$doc = new DOMDocument();
$doc->loadHTML("<div id='body'>{$input}</div>");
$root = $doc->getElementById('body');
$xp = new DOMXPath($doc);
$expression = './/div[not(@id)]';
while($r = $xp->query($expression, $root) and $r->length)
foreach($r as $div)
{
$new = $doc->createElement('p');
foreach($div->childNodes as $child)
$new->appendChild($child->cloneNode(1));
$div->parentNode->replaceChild($new, $div);
}
;
$html = '';
foreach($root->childNodes as $child)
$html .= rtrim($doc->saveHTML($child))
;
echo $html;
这会给你:
<p>Hello world!</p><p><div id="1">How <p>are you</p> today?</div></p><p>I am fine.</p>
答案 1 :(得分:1)
我采用了多种正则表达式的不同方法:
$text = "<div>Hello world!</div><div><div id=\"1\">How <div>are you</div> today?</div></div><div>I am fine.</div><div>an other <div id=\"2\">small</div>test</div><div>nested<div>divs</div>...</div>";
echo "before: " . $text . "\n";
do
{
$count1 = 0;
$text = preg_replace("/<div>((?![^<]*?<div).*?)<\/div>/", "<p>$1</p>", $text, -1, $count1);
$count2 = 0;
$text = preg_replace("/<div ([^>]+)>((?![^<]*?<div).*?)<\/div>/", "<temporarytag $1>$2</temporarytag>", $text, -1, $count);
} while ($count1 + $count2 > 0);
$text = preg_replace("/(<[\/]?)temporarytag/", "$1div", $text);
echo "after: " . $text;
这会让你:
before: <div>Hello world!</div><div><div id="1">How <div>are you</div> today?</div></div><div>I am fine.</div><div>an other <div id="2">small</div>test</div><div>nested<div>divs</div>...</div>
after: <p>Hello world!</p><p><div id="1">How <p>are you</p> today?</div></p><p>I am fine.</p><p>an other <div id="2">small</div>test</p><p>nested<p>divs</p>...</p>
如果你不需要这个片段,我至少自学了一些regexp:P