views:

155

answers:

1

I am trying to replace the html code inside the div 'resultsContainer' with the html of $response.

The result of my unsuccessful code is that the contents of 'resultsContainer' remain and the html of $response shows up on screen as text rather than being parsed as html.

Finally, I would like to inject the content of $response inside 'resultContainer' without having to create any new div, I need this: <div id='resultsContainer'>Html inside $response here...</div> and NOT THIS: <div id='resultsContainer'><div>Html inside $response here...</div></div>

   // Set Config
      libxml_use_internal_errors(true);   

      $doc = new DomDocument();
      $doc->strictErrorChecking = false;  
      $doc->validateOnParse = true;

      // load the html page
      $app = file_get_contents('index.php');

      $doc->loadHTML($app);

      // get the dynamic content
      $response = file_get_contents('search.php'.$query);
      $response = utf8_decode($response);         

      // add dynamic content to corresponding div
      $node = $doc->createElement('div', $response);
      $doc->getElementById('resultsContainer')->appendChild($node);


      // echo html snapshot
      echo $doc->saveHTML();
A: 

if $reponse is plain text:

// add dynamic content to corresponding div
$node = $doc->createTextNode($response);
$doc->getElementById('resultsContainer')->appendChild($node);

if it (can) contain html (one could use createDocumentFragment but that creates its own set of trouble with entities, dtd, etc.):

// add dynamic content to corresponding div
$frag = new DomDocument();
$frag->strictErrorChecking = false;  
$frag->validateOnParse = true;
$frag->loadHTML($response);
$target = $doc->getElementById('resultsContainer');
if(isset($target->childNodes) && $target->childNodes->length)){
    for($i = $target->childNodes->length -1; $i >= 0;$i--){
        $target->removeChild($target->childNodes->item($i));
    }
}
//if there's lots of content in $target, you might try this:
//$target->parentNode->replaceChild($target->cloneNode(false),$target);
foreach($frag->getElementsByTagName('body')->item(0)->childNodes as $node){
   $target->appendChild($doc->importNode($node,true));
}

Which goes to show it really isn't that suited (or at least cumbersome) to use DOMDocuments as a templating engine.

Wrikken
Hey, The problem is that $response is not plain text but html and what I really need is to replace the content of 'resultsContainer' rather than append to it
sala_7
So take the second option, and if you need to empty the element, do this before the foreach loop through $frag:foreach($target->childNodes as $node) $target->removeChild($node);
Wrikken
Thanks a lot, I'll try that and let you know how it went
sala_7
When doing that I am getting a: Warning: Invalid argument supplied for foreach() // empty target container $target = $doc->getElementById('resultsContainer'); foreach($target->childNodes as $node){ $target->removeChild($node); }
sala_7
may it be because $target is of type DOMElement and not DOMNode?
sala_7
Just that at that moment is has no content, see update code.
Wrikken
I tried the updated code but for some reason the original content inside 'resultsContainer' is not removed, so in the end it has its original content and additionally the content of $results. I am pulling my hear already so I think I'll try a different approach using preg_replace. Thanks a lot for the help.
sala_7
Hmmm would it be possible to get a (stripped down) version of the HTML created by index.php? I'm not ready to give up :)
Wrikken
I was finally able to delete the content of the div 'resultsContainer' using the following code: $doc->getElementById('resultsContainer')->nodeValue = ''; However, now, when I append the child I get <div id='resultsContainer'><html></body>...
sala_7
Indeed, changing that one is inadvisable. Care to put up that index.php on http://pastebin.com/ or something similar?
Wrikken
The contents of resultsContainer were not being deleted because of this: "In PHP 5.2.5 (Windows) it is not possible to iterate correctly over the DOMNodeList object returned by DOMNode->childNodes using foreach. Instead I had to use the for loop in conjunction with the item() method of DOMNodeList for iterating over all child nodes correctly.I don't know whether this is really a bug, but apparently it is."
sala_7
I was finally able to delete the content of resultsContainer using the following for loop: for($i = 0; $i < $target->childNodes->length; $i++){ $node = $target->childNodes->item($i); $target->removeChild($node);}The problem now is that $response is getting added right after the resultsContainer div. My brain is fried, tell me if you still need the code of index.php, I will send it after resting my head a bit
sala_7
Here is the new code:$frag = new DomDocument();$frag->strictErrorChecking = false; $frag->validateOnParse = true;$frag->loadHTML($response);$target = $doc->getElementById('resultsContainer');for($i = 0; $i < $target->childNodes->length; $i++){ $node = $target->childNodes->item($i); $target->removeChild($node);}foreach($frag->getElementsByTagName('body')->item(0)->childNodes as $node){ $target->appendChild($doc->importNode($node,true));}
sala_7
When using for() route: do it in reverse! You are changing the collection with every delete, so going from length to 0 catches all, 0 to length will jump (there is a new item(0) when you delete item(0)), will amend answer accordingly.
Wrikken