2010-05-06 5 views
10

Как изменить innerHTML php DOMElement?Изменение innerHTML php DOMElement

+0

Вы не можете напрямую. Вы должны будете иметь промежуточную функцию, чтобы взять строку и превратить ее в массив DOMElements. Вы могли бы написать это самостоятельно, хотя я уверен, что что-то подобное существует в Интернете. –

+0

В PHP классе DOMElement нет свойства innerHTML. Попробуйте посмотреть здесь: http://php.net/manual/en/class.domelement.php и здесь: http://www.php.net/manual/en/class.domtext.php – Babiker

ответ

0

Посмотрите на эту библиотеку PHP Simple HTML DOM Parser http://simplehtmldom.sourceforge.net/

Это выглядит довольно просто. Вы можете изменить innertext свойство ваших элементов. Это может помочь.

+1

PHP, а не JavaScript .. PHP-реализация DOM не имеет свойства 'innerHTML'. –

+1

Да, моя вина. но php5 HTML DOM parser имеет «внутренний текст». http://simplehtmldom.sourceforge.net/ – Jull

+0

Это не библиотека, на которую ссылался OP. См .: http://php.net/manual/en/book.dom.php. Но вы можете отредактировать свой ответ и ссылку на найденную библиотеку и посмотреть, хочет ли OP переключиться. –

1

Я думаю, что самое лучшее, что вы можете сделать, это придумать функцию, которая возьмет DOMElement, который вы хотите изменить InnerHTML, скопируйте и замените.

В очень грубом PHP:

function replaceElement($el, $newInnerHTML) { 
    $newElement = $myDomDocument->createElement($el->nodeName, $newInnerHTML); 
    $el->parentNode->insertBefore($newElement, $el); 
    $el->parentNode->removeChild($el); 

    return $newElement; 
} 

Это не принимает во внимание атрибутов и вложенных структур, но я думаю, что это поможет вам на вашем пути.

+2

Для кого-то еще, проверяющего этот код, мне пришлось использовать $ el-> parentNode-> insertBefore вместо $ el-> insertBefore. – whichdan

+0

Это работает для установки innerText не innerHTML. Второй параметр createElement не принимает форматирование html. – Greg

+0

Согласен, @greg. Это будет кодировать символы HTML. – Kafoso

7

мне нужно сделать это для проекта в последнее время и в конечном итоге с расширением до DOMElement: http://www.keyvan.net/2010/07/javascript-like-innerhtml-access-in-php/

Вот пример, показывающий, как он используется:

<?php 
require_once 'JSLikeHTMLElement.php'; 
$doc = new DOMDocument(); 
$doc->registerNodeClass('DOMElement', 'JSLikeHTMLElement'); 
$doc->loadHTML('<div><p>Para 1</p><p>Para 2</p></div>'); 
$elem = $doc->getElementsByTagName('div')->item(0); 

// print innerHTML 
echo $elem->innerHTML; // prints '<p>Para 1</p><p>Para 2</p>' 

// set innerHTML 
$elem->innerHTML = '<a href="http://fivefilters.org">FF</a>'; 

// print document (with our changes) 
echo $doc->saveXML(); 
?> 
0

Вот заменить классом функции I просто написал (а):

Он заменит innerHtml класса. Вы также можете указать тип узла, например. DIV/р/а и т.д.

function replaceInnerHtmlByClass($html, $replace=null, $class=null, $nodeType=null){ 
    if(!$nodeType){ $nodeType = '*'; } 
    $dom = new DOMDocument(); 
    $dom->loadHTML($html); 
    $xpath = new DOMXPath($dom); 
    $nodes = $xpath->query("//{$nodeType}[contains(concat(' ', normalize-space(@class), ' '), '$class')]"); 
    foreach($nodes as $node) { 
    while($node->childNodes->length){ 
     $node->removeChild($node->firstChild); 
    } 
    $fragment = $dom->createDocumentFragment(); 
    $fragment->appendXML($replace); 
    $node->appendChild($fragment); 
    } 
    return $dom->saveHTML($dom->documentElement); 
} 

Вот еще одна функция, которую я написал, чтобы удалить узлы с определенным классом, но сохраняя внутреннюю HTML.

Установка замены на истину будет отбрасывать внутренний html.

Установка замены на любой другой контент заменит внутренний html предоставленным контентом.

function stripTagsByClass($html, $class=null, $nodeType=null, $replace=false){ 
    if(!$nodeType){ $nodeType = '*'; } 
    $dom = new DOMDocument(); 
    $dom->loadHTML($html); 
    $xpath = new DOMXPath($dom); 
    $nodes = $xpath->query("//{$nodeType}[contains(concat(' ', normalize-space(@class), ' '), '$class')]"); 
    foreach($nodes as $node) { 
    $innerHTML = ''; 
    $children = $node->childNodes; 
    foreach($children as $child) { 
     $tmp = new DOMDocument(); 
     $tmp->appendChild($tmp->importNode($child,true));  
     $innerHTML .= $tmp->saveHTML(); 
    } 
    $fragment = $dom->createDocumentFragment(); 
    if($replace !== null && $replace !== false){ 
     if($replace === true){ $replace = ''; } 
     $innerHTML = $replace; 
    } 
    $fragment->appendXML($innerHTML); 
    $node->parentNode->replaceChild($fragment, $node); 
    } 
    return $dom->saveHTML($dom->documentElement); 
} 

Функции тезисов могут быть легко адаптированы для использования в качестве селектора других атрибутов.

Мне нужно было только оценить атрибут класса.

1

Кажется, что appendXML не работает всегда - например, если вы попытаетесь добавить XML с 3 уровнями.Вот функция, я писал, что всегда работает (вы хотите установить $ содержание, как innerHTML для $ элемента):

function setInnerHTML($DOM, $element, $content) { 
    $DOMInnerHTML = new DOMDocument(); 
    $DOMInnerHTML->loadHTML($content); 
    $contentNode = $DOMInnerHTML->getElementsByTagName('body')->item(0)->firstChild; 
    $contentNode = $DOM->importNode($contentNode, true); 
    $element->appendChild($contentNode); 
    return $elementNode; 
} 
+1

Возвращаемая переменная '$ elementNode' не определена - не должно быть' $ contentNode'? Вы можете упростить функцию, используя '$ element-> ownerDocument' вместо того, чтобы проходить в' $ DOM'. Это импортирует только первый дочерний элемент любого содержимого. Чтобы импортировать весь фрагмент, удалите '-> firstChild 'в строке 4. –

-1

вот как вы это делаете:

$doc = new DOMDocument(''); 
$label = $doc->createElement('label'); 

$label->appendChild($doc->createTextNode('test')); 
$li->appendChild($label); 

echo $doc->saveHTML(); 
0

Разработка дальше от ответа Джоанна Гох в эта функция будет вставить либо текстовый узел или фрагмент HTML:

function nodeFromContent($node, $content) { 
    //creates a text node, or dom node if content contains html 
    $lt = strpos($content, '<'); 
    $gt = strrpos($content, '>'); 
    if (!($lt === false || $gt === false) && $gt > $lt) { 
     //< followed by > means potentially contains HTML 
     $DOMInnerHTML = new DOMDocument(); 
     $DOMInnerHTML->loadHTML($content); 
     $contentNode = $DOMInnerHTML->getElementsByTagName('body')->item(0); 
     $newNode = $node->ownerDocument->importNode($contentNode, true); 
    } else { 
     $newNode = $node->ownerDocument->createTextNode($content); 
    } 
    return $newNode; 
} 

использования

$newNode = nodeFromContent($node, $content); 
$node->parentNode->insertBefore($newNode, $node); 
//or $node->appendChild($newNode) depending on what you require 
0
function setInnerHTML($DOM, $element, $innerHTML) { 
    $node = $DOM->createTextNode($innerHTML); 
    $element->appendChild($node); 
} 
2

Другое решение:

1) создать новый DOMDocumentFragment из HTML строки для вставки; 2) удалить старый контент нашего элемента, удалив его дочерние узлы; 3) добавьте DOMDocumentFragment к нашему элементу.

function setInnerHTML($element, $html) 
{ 
    $fragment = $element->ownerDocument->createDocumentFragment(); 
    $fragment->appendXML($html); 
    while ($element->hasChildNodes()) 
     $element->removeChild($element->firstChild); 
    $element->appendChild($fragment); 
} 

В качестве альтернативы, мы можем заменить наш элемент с clean copy, а затем добавить к DOMDocumentFragment этого клона.

function setInnerHTML($element, $html) 
{ 
    $fragment = $element->ownerDocument->createDocumentFragment(); 
    $fragment->appendXML($html); 
    $clone = $element->cloneNode(); // Get element copy without children 
    $clone->appendChild($fragment); 
    $element->parentNode->replaceChild($clone, $element); 
} 

Тест:

$doc = new DOMDocument(); 
$doc->loadXML('<div><span style="color: green">Old HTML</span></div>'); 
$div = $doc->getElementsByTagName('div')->item(0); 
echo $doc->saveHTML(); 

setInnerHTML($div, '<p style="color: red">New HTML</p>'); 
echo $doc->saveHTML(); 

// Output: 
// <div><span style="color: green">Old HTML</span></div> 
// <div><p style="color: red">New HTML</p></div> 
+0

Хотя этот фрагмент кода может решить вопрос, [включая объяснение] (// meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин вашего предложения кода. Также попробуйте не толковать код с пояснительными комментариями, что уменьшает читаемость кода и объяснений! –

1

Я закончил тем, что делает эту функцию с помощью нескольких функций от других людей на этой странице. Я изменил один из Joanna Goch так, что Peter Brand говорит в основном, а также добавил код от Гость и из других мест.

Эта функция не использует расширение и не использует appendXML (который очень разборчив и разрывается, даже если он видит один тег BR, который не закрыт) и, кажется, работает хорошо.

function set_inner_html($element, $content) { 
    $DOM_inner_HTML = new DOMDocument(); 
    $internal_errors = libxml_use_internal_errors(true); 
    $DOM_inner_HTML->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8')); 
    libxml_use_internal_errors($internal_errors); 
    $content_node = $DOM_inner_HTML->getElementsByTagName('body')->item(0); 
    $content_node = $element->ownerDocument->importNode($content_node, true); 
    while ($element->hasChildNodes()) { 
     $element->removeChild($element->firstChild); 
    } 
    $element->appendChild($content_node); 
} 
Смежные вопросы