2015-11-27 4 views
1

Я не знаю, можете ли вы прочитать JS JQuery, но это то, что я хотел бы сделать на стороне сервера, а не на стороне клиента: $('p').wrapInner('<span class="contentsInP" />'); Я хотел бы взять все существующие абзацы со страницы и обернуть их содержимое в новом диапазоне с определенным классом.PHP XPath как обернуть содержимое p в промежутке

К счастью, все мои документы HTML5 в XML вкус и действительно так, что в PHP я могу сделать это (упрощенный):

$xml=new DOMDocument(); 
$xml->loadXML($html); 
$xpath = new DOMXPath($xml); 
// How to go on in here to wrap my p's? 
$output=$xml->saveXML(); 

Как получить РНР DOMXPath делать свою обертку?

EDIT: повозился с этим на основе комментария, но не могли заставить его работать

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

выше оборачивает р в пролете, но мне нужен пролет обертывания содержимого P, сохраняя при этом р вокруг пролета ... Кроме того, выше вышло, если p имеет класс, то он не будет затронут.

+0

связаны: http://stackoverflow.com/questions/8426391/wrap-all-images-with- a-div-using-domdocument – har07

+0

@ har07 теперь с этим примером работает в течение часа, но не смог заставить его работать для содержимого p - я добавил код до тех пор, пока не дошел до вопроса ... –

ответ

1

В попытке адаптировать этот другой ответ, основную вещь, которую необходимо изменить с ним, чтобы получить все дочерние узлы <p> элемента, первый удалить их как ребенок из <p> затем добавить их как ребенок на <span>. Затем, наконец, добавьте <span> в качестве дочернего узла <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(); 

Учитывая ввод HTML-фрагмент, то это должно производить выход, как: (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> 
+0

При использовании этого добавленные узлы получают пространство имен, подобное этому в HTML для меня: «
« Вы знаете, почему это так? –

+0

@ C.O. Вероятно, из-за использования 'saveXML()' вместо 'saveHTML()'. –