任务:
-
所有出现的情况都必须替换为常数
DEVICE
的值,我已经使用其他函数定义了该值BUT不应从包装在<pre>
和<code>
标记内的代码中替换。 -
此任务需要在不使用任何JavaScript的情况下完成。
样品标记:
<div class="wrapper">
<img src="img/demo/desktop-img/sample1.jpg" width="200" height="200" alt="image">
<img src="img/demo/desktop-img/sample2.jpg" width="200" height="200" alt="image">
<pre>
<img src="img/demo/desktop-img/sample1.jpg" width="200" height="200" alt="image">
<img src="img/demo/desktop-img/sample2.jpg" width="200" height="200" alt="image">
</pre>
<code>
<img src="img/demo/desktop-img/sample1.jpg" width="200" height="200" alt="image">
<img src="img/demo/desktop-img/sample2.jpg" width="200" height="200" alt="image">
</code>
</div>
我尝试了以下操作,但它也替换了<pre>
和<code>
标记中的出现,这正是不应该发生的事情。我使用PHP作为我的编程语言。
$content = str_replace('/desktop-img/', '/' . DEVICE . '-img/', $content);
我甚至尝试了以下操作,但没有成功
<?php
function changeImagePaths ($content) { // content here comes as string via some other functon.
$dom = new DOMDocument;
$dom->loadHTML($content);
$nodes = $dom->getElementsByTagName('[self::img][not(ancestor::pre) and not(ancestor::code)]');
foreach( $nodes as $node ) {
// What is the correct way to retrive all image-paths
// that are not wrapped within <pre> or <code> tags and how to use them in the code?
$node->nodeValue = str_replace('desktop-img', DEVICE, $node->nodeValue);
}
$content = $dom->saveHTML();
return $content;
}
?>
挑战:
我认为使用DOM方法应该是可能的,但我无法找出正确的语法。
我对编程很陌生,因此仍在学习过程中。请温和一点,用代码示例说明你的答案,以便于理解。
我的问题:
- DOM方法的正确语法应该是什么
- 使用DOM是正确的方法吗
- 使用DOM方法会有任何挑战/性能打击吗
- 在不使用JavaScript的情况下,还有其他更好的方法吗
这是一个快速的工作,所以看起来可能不太好,但希望你能明白。
在线演示
function walkDOM($node)
{
if($node->nodeName=="pre" || $node->nodeName=="code")
{
return;
}
elseif($node->nodeName=="img")
{
$node->attributes->getNamedItem("src")->nodeValue=str_replace('desktop-img','mobile-img',$node->attributes->getNamedItem("src")->nodeValue);
}
elseif($node->hasChildNodes())
{
foreach($node->childNodes as $child)
{
walkDOM($child);
}
}
}
function changeImagePath($html)
{
$dom=new DOMDocument;
$dom->preserveWhiteSpace=true;
$dom->loadHTML($html);
$root=$dom->documentElement;
walkDOM($root);
$dom->formatOutput=false;
return $dom->saveHTML($root);
}
这个想法是递归地遍历DOM树,跳过每个<pre>
和<code>
,并更改遇到的所有<img>
。
这是非常直接的,但您可能会注意到,由于您将其视为HTML,DOM会自动添加一些标签来"实现"它,并以一种(IMO)非常奇怪的方式对其进行格式化。
Xpath是您的朋友:
$xpath = new DOMXpath($dom);
foreach($xpath->query('//img[not(ancestor::pre) and not(ancestor::code)]') as $img){
$img->setAttribute('src', 'foo');
}
$path1='C:/ff/ss.html';
$file=file_get_contents($path1);
$dom = new DOMDocument;
@$dom->loadHTML($file);
$links = $dom->getElementsByTagName('img');
//extract img src path from the html page
foreach ($links as $link) {
$re= $link->getAttribute('src');
$a[]=$re;
}
$oldpth=explode('/',$path1);
$c=count($oldpth)-1;
$fname=$oldpth[$c];
$pth=array_slice($oldpth,0,$c);
$cpth=implode('/',$pth);
foreach($a as $v) {
if(is_file ($cpth.'/'.$v)) {
$c=explode('/',$v);
$c[0]="xyz007";
$f=implode('/',$c);
$file=str_replace ($v,$f,$file);
}
}
$path2='D:/mail/newpath/';
$wnew=fopen($path2.$fname,'w+');
fwrite($wnew,$file);