2016-06-22 9 views
1

У меня есть этот HTML строку в DOMElement:DOMElement заменить значение HTML

<h1>Home</h1> 
test{{test}} 

Я хочу, чтобы заменить этот материал таким образом, что только

<h1>Home</h1> 
test 

остается (так что я хочу, чтобы удалить {{test}}).

В этот момент мой код выглядит следующим образом:

$node->nodeValue = preg_replace(
    '/(?<replaceable>{{([a-z0-9_]+)}})/mi', '' , $node->nodeValue); 

Это не работает, потому что nodeValue не содержит значение HTML узла. Я не могу понять, как получить строку HTML узла, кроме использования $node->C14N(), но используя C14N Я не могу заменить содержимое. Любые идеи, как я могу удалить {{test}} в такой HTML-строке?

ответ

1

Вы пробовали функцию DOMDocument::saveXML? (http://php.net/manual/en/domdocument.savexml.php)

У него есть второй аргумент $node, с помощью которого вы можете указать, какой узел должен печатать HTML/XML.

Так, например:

<?php 

$doc = new DOMDocument('1.0'); 
// we want a nice output 
$doc->formatOutput = true; 

$root = $doc->createElement('body'); 
$root = $doc->appendChild($root); 

$title = $doc->createElement('h1', 'Home'); 
$root->appendChild($title); 

$text = $doc->createTextNode('test{{test}}'); 
$text = $root->appendChild($text); 

echo $doc->saveXML($root); 

?> 

Это даст вам:

<body> 
    <h1>Home</h1> 
    test{{test}} 
</body> 

Если вы не хотите <body> тег, вы могли бы цикл через все его ChildNodes:

<?php 

foreach($root->childNodes as $child){  
    echo $doc->saveXML($child); 
} 

?> 

Это даст вам:

<h1>Home</h1>test{{test}} 

Edit: вы можете, конечно, заменить {{test}} на регулярное выражение, что вы уже используете:

<?php 

$xml = ''; 
foreach($root->childNodes as $child){  
    $xml .= preg_replace(
       '/(?<replaceable>{{([a-z0-9_]+)}})/mi', '', 
       $doc->saveXML($child) 
    ); 
} 

?> 

Это даст вам:

<h1>Home</h1>test 

Примечание: Я не тестировал кода, но это должно дать вам общую идею.

1

Проблема главным образом связана с тем, как вы перемещаетесь по DOM, но есть проблема с вашим RegExp; XPath фактически обеспечивает большую гибкость, когда дело доходит до манипуляции с DOM, так что это мое предпочтительное решение.

Предполагая, что вы есть DOMDocument построен, как это (я прикрепил XPath):

$dom = new DOMDocument('1.0', 'utf-8'); 
$xpath = new DOMXPath($dom); 

$node = $dom->createElement('div'); 
$node->appendChild(
    $dom->createElement('h1', "Home") 
    ); 
$node->appendChild(
    $dom->createTextNode("test{{test}}") 
    ); 

$dom->appendChild($node); 

Вы можете настраивать таргетинг текстовый узел этого <div> с '/div/text()' в XPath.

Так заменить {{test}} внутри этого текстового узла, не повреждать остальную часть узла, вы могли бы сделать:

$xpath->query('/div/text()')->item(0)->nodeValue = preg_replace(
     '/(.*){{[^}]+}}/m', 
     '$1', 
     $xpath->query('/div/text()')->item(0)->nodeValue 
); 

Несколько запутанная, но выход из $dom->saveXML(); является:

<?xml version="1.0" encoding="utf-8"?> 
<div><h1>Home</h1>test</div> 

{{test}} было удалены, оставив неповрежденным.

+0

У меня только есть узел DOMElement, доступный на данный момент, я не могу использовать dom или xpath. Или я должен загрузить его как xpath. – SheperdOfFire

+0

Вы можете просто загрузить узел в DOMDocument с помощью «составленного» корневого узла, а затем просто извлечь исходный элемент, когда вы его обработали. – CD001