0

I have the following html code stored in a php variable:

<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">

And I have a php array which has three elements, exactly as many as the image elements in the html string:

Array(3){
         [0]<img src="img/new1.jpg">
         [1]<img src="img/new2.jpg">
         [2]<img src="img/new3.jpg">
}

I'm trying to write a function which will replace the first img tag in the html string with the first array element, the second one with the second in the array and the third with the third in the array. So that at the end I get this:

<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">

Believe me I've no idea how to do this. If I would have an idea I would try but the problem is that I can't come to any logic for solving this problem. Any help would be really great.

13
  • You can change array new elements? Commented Mar 19, 2016 at 21:55
  • The number of images is constantly 3 or is it changing? Commented Mar 19, 2016 at 21:55
  • @GyulaSoós the number of the image tags in the html string will be always equal to the number of the image tags in the array. Commented Mar 19, 2016 at 21:56
  • Split (explode in php), trim, indexOf img, replace, use counter for correct array index. Commented Mar 19, 2016 at 21:57
  • 3
    What I don't understand in this question, is when you need this to happen. Is the page already rendered and then you want to replace it, or do you want to echo the elements with data from the PHP array while the page is still loading? Commented Mar 19, 2016 at 22:17

4 Answers 4

2

If you're able to have your new image tag array hold only the path/file info rather than entirely new HTML tags then something similar to the following should work:

$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();

Note: You can modify your new image array to have only path/image using preg_replace or str_replace.

UPDATE BASED ON YOUR REPLY AND REQUEST FOR IMPROVEMENT IN ANSWER BELOW:

  • I forgot this with my earlier reply but as of PHP 5.4 and Libxml 2.6, loadHTML() accepts Libxml parameters. You can drop all the str_replace() stuff (see code).
  • There's no need to copy your argument into a local variable if $content is a simple string, as it'll be passed by value anyway (the original won't be modified).
  • I would not supress errors using @, use libxml_use_internal_errors and libxml_get_errors instead, in this instance.
  • As I mentioned in my comment, I don't see $imagetag_arr being passed to the function, declared global, or in front of $this. I've added it to the arg list of the function with a more descriptive name.

Updated code:

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();
}

Sign up to request clarification or add additional context in comments.

Comments

2
$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);

If you want to replace at a higher level in the HTML object tree, you'll need to use a Dom parser, or run into problems with the likes of:

<img
    src='img/1.jpg'
>

Comments

1

Try this:

$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
);

It's tested and it works.
But maybe somebody could find a more elegant way of using $new and $i?

2 Comments

This code works with one exception. All image tags are replaced by the first array element. $new[$i++] seems not to work.
@DevMan Oh... sorry. As I said, it was tested, but I was focused on checking "new", so I didn't pay attention to the numbers! I edited my answer and now sure it works.
-1

Thanks to all for your answers. I've some-kind combined all the answers and came to the following solution. It's not the best one from coding perspective and I really feel bad about myself because of writing this "amateur" script. But it's working under all conditions. If someone can improve this code I would be very thankful.

$content is my html string. $imagetag_arr is the array with the new image tags.

 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;
    }

4 Comments

@avip Sorry my bad. $imagetag_arr is the array, filled with the new image tags. I don't know why someone down-voted my answer. What's wrong with it?
I don't see $imagetag_arr being passed to the function, declared global, or in front of $this, so that function won't work. I didn't downvote it so I've no idea what the reasoning for that was.
I've updated my original answer with some suggested improvements as you've asked

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.