我在php变量中存储了以下html代码:
<p>This is a sample paragraph</p>
<img src="img/1.jpg">
<h1>This is my header</h1>
<img src="img/2.jpg">
<p>I hope someone can help me</p>
<img src="img/3.jpg">
我有一个 php 数组,它有三个元素,与 html 字符串中的图像元素一样多:
Array(3){
[0]<img src="img/new1.jpg">
[1]<img src="img/new2.jpg">
[2]<img src="img/new3.jpg">
}
我正在尝试编写一个函数,该函数将用第一个数组元素替换 html 字符串中的第一个 img 标签,用数组中的第二个元素替换第二个,用数组中的第三个元素替换第三个。所以最后我得到这个:
<p>This is a sample paragraph</p>
<img src="img/new1.jpg">
<h1>This is my header</h1>
<img src="img/new2.jpg">
<p>I hope someone can help me</p>
<img src="img/new3.jpg">
相信我,我不知道该怎么做。如果我有一个想法,我会尝试,但问题是我无法得出解决这个问题的任何逻辑。任何帮助都会很棒。
如果您能够让新的图像标签数组仅包含路径/文件信息而不是全新的 HTML 标签,那么类似于以下内容的内容应该可以工作:
$html = <<<'HTML'
<p>This is a sample paragraph</p>
<img src="img/1.jpg">
<h1>This is my header</h1>
<img src="img/2.jpg">
<p>I hope someone can help me</p>
<img src="img/3.jpg">
HTML;
$newImages = ['img/new1.jpg', 'img/new2.jpg', 'img/new3.jpg'];
$dom = new DOMDocument;
$dom->loadHTML($html);
$images = $dom->getElementsByTagName('img');
for ($i = 0; $i < $images->length; $i++)
$images->item($i)->setAttribute('src', $newImages[$i]);
// Your updated HTML is now in $html
$html = $dom->saveHTML();
注意:您可以使用 preg_replace
或 str_replace
将新图像数组修改为仅包含路径/图像。
回复和以下答案的改进请求进行更新:
- 我在之前的回复中忘记了这一点,但从 PHP 5.4 和 Libxml 2.6 开始,
loadHTML()
接受 Libxml 参数。你可以删除所有str_replace()
的东西(见代码)。 - 如果参数是一个简单的字符串,则无需将参数复制到局部变量
$content
因为它无论如何都会按值传递(原始字符串不会被修改)。 - 在这种情况下,我不会使用
@
来抑制错误,而是使用 libxml_use_internal_errors 和 libxml_get_errors。 - 正如我在评论中提到的,我没有看到
$imagetag_arr
被传递给函数、声明全局或$this
前面。我已将其添加到函数的arg列表中,并具有更具描述性的名称。
更新的代码:
function replaceTags($content, $newImages)
{
$dom = new DOMDocument();
$dom->loadHTML($content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$images = $dom->getElementsByTagName('img');
for ($i = 0; $i < $images->length; $i++)
{
$dom2 = new DOMDocument();
$dom2->loadHTML($newImages[$i]);
$newImg = $dom2->getElementsByTagName('img')
->item(0);
$images->item($i)->setAttribute('src', $newImg->getAttribute('src'));
}
return $dom->saveHTML();
}
$a=Array (
'img/1.jpg'=>'img/new1.jpg',
'img/2.jpg'=>'img/new2.jpg',
'img/3.jpg'=>'img/new3.jpg');
$replace=array_values($a);
$find=array_keys($a);
$html=str_replace($find, $replace, $html);
如果要在HTML对象树中的更高级别进行替换,则需要使用Dom解析器,否则会遇到以下问题:
<img
src='img/1.jpg'
>
试试这个:
$source = <<<'EOD'
<p>This is a sample paragraph</p>
<img src="img/1.jpg">
<h1>This is my header</h1>
<img src="img/2.jpg">
<p>I hope someone can help me</p>
<img src="img/3.jpg">
EOD;
$new = [
'<img src="img/new1.jpg">',
'<img src="img/new2.jpg">',
'<img src="img/new3.jpg">',
];
$i = 0;
$result = preg_replace_callback(
'/<img src="img'/[^.]+'.jpg">/',
function($matches) use ($new, &$i) {
return $new[$i++];
},
$source
);
它经过测试并且可以工作。
但也许有人可以找到一种更优雅的方式来使用$new
和$i
?
感谢大家的回答。我已经以某种方式结合了所有答案,并得出了以下解决方案。从编码的角度来看,这不是最好的,因为写了这个"业余"脚本,我真的对自己感觉不好。但它在所有条件下都有效。如果有人可以改进此代码,我将不胜感激。
$content是我的 html 字符串。$imagetag_arr 是带有新图像标记的数组。
function replaceTags($content){
$html = $content; //content is my html string.
$dom = new DOMDocument;
$dom->loadHTML($html);
$images = $dom->getElementsByTagName('img');
for ($i = 0; $i < $images->length; $i++) {
$dom2 = new DOMDocument();
@$dom2->loadHTML($imagetag_arr[$i]);
$search = $dom2->getElementsByTagName('img');
foreach ($search as $item) {
$newsrc=$item->getAttribute('src');
}
$images->item($i)->setAttribute('src', $newsrc);
}
// my updated HTML is now in $html
$html = $dom->saveHTML();
//because I've saved it as html now the dom object is appending all the html
//and body tags to my $final result so I've replaced
// them all with empty strings.I hate myself
// for doing it like this.
$finalhtml=preg_replace('/<![^>]+>/i','',$html);
$finalhtml=str_replace('<html>','',$finalhtml);
$finalhtml=str_replace('<body>','',$finalhtml);
$finalhtml=str_replace('</body>','',$finalhtml);
$finalhtml=str_replace('</html>','',$finalhtml);
return $finalhtml;
}