DOMElement заменяет значение HTML

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

<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> тег, вы можете перебрать все его дочерние узлы:

<?php

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

?>

Это даст вам:

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

Изменить: вы можете, конечно, заменить {{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}} был удален, оставив остальные нетронутыми.

1