3

I want to replace all <span> tags with <p> using phpquery. What is wrong with my code? It finds the span but the replaceWith function is not doing anything.

$event = phpQuery::newDocumentHTML(file_get_contents('event.html'));
$formatted_event = $event->find('span')->replaceWith('<p>');

This documentation indicates this is possible:
http://code.google.com/p/phpquery/wiki/Manipulation#Replacing
http://api.jquery.com/replaceWith/

This is the html that gets returned with and without ->replaceWith('<p></p>') in the code:

<span class="Subhead1">Event 1<br></span><span class="Subhead2">Event 2<br>
    August 12, 2010<br>
    2:35pm <br>
    Free</span>
1
  • phpQuery adds a new element after the current one, but ultimately returns the original and not the element which was inserted (replaced). $formatted_event will be the result of the initial find because of this. $event however will have its contents changed. Commented Dec 5, 2011 at 22:19

5 Answers 5

3

If you dont mind a plain DOMDocument solution (DOMDocument is used unter the hood of phpQuery to parse the HTML fragments), I did something similiar a while ago. I adapted the code to do what you need:

$document = new DOMDocument();

// load html from file
$document->loadHTMLFile('event.html');

// find all span elements in document
$spanElements = $document->getElementsByTagname('span');
$spanElementsToReplace = array();

// use temp array to store span elements
// as you cant iterate a NodeList and replace the nodes
foreach($spanElements as $spanElement) {
  $spanElementsToReplace[] = $spanElement;
}

// create a p element, append the children of the span to the p element, 
// replace span element with p element
foreach($spanElementsToReplace as $spanElement) {
    $p = $document->createElement('p');

    foreach($spanElement->childNodes as $child) {
        $p->appendChild($child->cloneNode(true));
    }

    $spanElement->parentNode->replaceChild($p, $spanElement);
} 

// print innerHTML of body element
print DOMinnerHTML($document->getElementsByTagName('body')->item(0));


// --------------------------------


// Utility function to get innerHTML of an element
// -> "stolen" from: http://www.php.net/manual/de/book.dom.php#89718
function DOMinnerHTML($element) {
    $innerHTML = "";
    $children = $element->childNodes;
    foreach ($children as $child)
    {
        $tmp_dom = new DOMDocument();
        $tmp_dom->appendChild($tmp_dom->importNode($child, true));
        $innerHTML.=trim($tmp_dom->saveHTML());
    }
    return $innerHTML;
} 

Maybe this can get you in the right direction on how to do the replacement in phpQuery?


EDIT:

I gave the jQuery documentation of replaceWith another look, it seems to me, that you have to pass in the whole html fragment which you want to be your new, replaced content.

This code snipped worked for me:

$event = phpQuery::newDocumentHTML(...);

// iterate over the spans
foreach($event->find('span') as $span) {
// make $span a phpQuery object, otherwise its just a DOMElement object
$span = pq($span);
// fetch the innerHTMLL of the span, and replace the span with <p>
$span->replaceWith('<p>' . $span->html() . '</p>');
}

print (string) $event;

I couldnt find any way to do this with chained method calls in one line.

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

3 Comments

+1 - Thanks a lot for posting this. Going to play around with it. This is written well and easily to read. Will make a great launching point for learning how phpquery is manipulating. Blackboxes are only good until they don't work :). I would still like to know why manipulation in phpquery isn't working from my code. I was hoping someone familiar with phpquery could validate if my query: $formatted_event = $event->find('span')->replaceWith('<p></p>'); is written correctly and works.
@acidjazz thanks! I gave it another try with phpQuery, please see my edit. :-)
This is perfect. It returned the magic to phpquery :). Using the pq() function was what had me hung up. This code works also: $span = pq($event->find('span')) ; $span->replaceWith('<p>' . $span->html() . '</p>'); Just takes the foreach out of the picture. Thanks!
2

Wont str_replace do a better job at this? Its faster and easier to debug. Always take into consideration that external libraries may have bugs:)

$htmlContent = str_replace("<span", "<p", $htmlContent);
$htmlContent = str_replace("</span>", "</p>", $htmlContent);    

1 Comment

+1 - If by faster and easier, you mean, not wasting 3 hours trying to make phpquery do what I already knew how to do, then you are correct Sir! :) The idea of phpquery / jquery performing manipulation tasks is appealing since it should be easy to string manipulation functions together. When it doesn't work, it is a pain. I'm probably using the wrong syntax for the phpquery manipulation functions, because none of them seem to work. All the traverse functions work like magic.
1

Try;

$formatted_event = $event->find('span')->replaceWith('<p></p>');

2 Comments

I'm assuming op is looking to turn all of the spans into paragraphs but keeping content?
Yes wanting to keep the content. I thought using ->replaceWith('<p></p>') would work also, but replaceWith just seems to do nothing. I'm not getting any errors from phpquery. I edited my post to show the html I'm trying to change.
0

Did you try:

 $formatted_event = $event->find('span')->replaceWith('p');

Comments

0

You could actually use the wrap function

$event = phpQuery::newDocumentHTML(...);

// iterate over the spans
foreach($event->find('span') as $span) {
  // make $span a phpQuery object, otherwise its just a DOMElement object
  $span = pq($span);
  // wrap the span with <p>
  $span->wrap('<p></p>');
}

print (string) $event;

1 Comment

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.