Reputation: 2329
I don't know if you can read JS Jquery but this is what I'd like to do server sided instead of client sided: $('p').wrapInner('<span class="contentsInP" />');
I'd like to take all existing paragraphs from a page and wrap their contents in a new span with a specific class.
Luckily all my documents are HTML5 in its XML flavour and are valid so that in PHP I can do this (simplified):
$xml=new DOMDocument();
$xml->loadXML($html);
$xpath = new DOMXPath($xml);
// How to go on in here to wrap my p's?
$output=$xml->saveXML();
How do I get PHP's DOMXPath to do my wrapping?
EDIT: Fiddled with this based on the comment but couldn't make it work
// based on http://stackoverflow.com/questions/8426391/wrap-all-images-with-a-div-using-domdocument
$xml=new DOMDocument();
$xml->loadXML(utf8_encode($temp));
$xpath = new DOMXPath($xml);
//Create new wrapper div
$new_span = $xml->createElement('span');
$new_span->setAttribute('class','contentsInP');
$ps = $xml->getElementsByTagName('p');
//Find all p
//Iterate though p
foreach ($ps AS $p) {
//Clone our created span
$new_span_clone = $new_span->cloneNode();
//Replace p with this wrapper span
$p->parentNode->replaceChild($new_span_clone,$p);
//Append the p's contents to wrapper span
// THIS IS THE PROBLEM RIGHT NOW:
$new_span_clone->appendChild($p);
}
$temp=$xml->saveXML();
The above wraps the p in a span but I need a span wrapping the p's contents while keeping the p around the span... Furthermore the above fails if the p has a class, then it won't be touched.
Upvotes: 1
Views: 600
Reputation: 270677
In attempting to adapt that other answer, the primary thing that needs to change with it is to get all child nodes of the <p>
element, first remove them as children from <p>
then append them as children onto the <span>
. Then finally, append the <span>
as a child node of the <p>
.
$html = <<<HTML
<!DOCTYPE html>
<html>
<head><title>xyz</title></head>
<body>
<div>
<p><a>inner 1</a></p>
<p><a>inner 2</a><div>stuff</div><div>more stuff</div></p>
</div>
</body>
</html>
HTML;
$xml=new DOMDocument();
$xml->loadXML(utf8_encode($html));
//Create new wrapper div
$new_span = $xml->createElement('span');
$new_span->setAttribute('class','contentsInP');
$ps = $xml->getElementsByTagName('p');
//Find all p
//Iterate though p
foreach ($ps AS $p) {
//Clone our created span
$new_span_clone = $new_span->cloneNode();
// Get an array of child nodes from the <p>
// (because the foreach won't work properly over a live nodelist)
$children = array();
foreach ($p->childNodes as $child) {
$children[] = $child;
}
// Loop over that list of child nodes..
foreach ($children as $child) {
// Remove the child from the <p>
$p->removeChild($child);
// Append it to the span
$new_span_clone->appendChild($child);
}
// Lastly, append the <span> as a child to the <p>
$p->appendChild($new_span_clone);
}
$temp=$xml->saveXML();
Given the input HTML fragment, this should produce output like: (demonstration...)
<!DOCTYPE html>
<html>
<head><title>xyz</title></head>
<body>
<div>
<p><span class="contentsInP"><a>inner 1</a></span></p>
<p><span class="contentsInP"><a>inner 2</a><div>stuff</div><div>more stuff</div></span></p>
</div>
</body>
</html>
Upvotes: 1