Из этого вопроса: Какой шаблон регулярного выражения мне нужен? Я использовал следующий код:
function process($node, $replaceRules) { if($node->hasChildNodes()) { foreach ($node->childNodes as $childNode) { if ($childNode instanceof DOMText) { $text = preg_replace( array_keys($replaceRules), array_values($replaceRules), $childNode->wholeText ); $node->replaceChild(new DOMText($text),$childNode); } else { process($childNode, $replaceRules); } } } } $replaceRules = array( '/\b(c|C)olor\b/' => '$1olour', '/\b(kilom|Kilom|M|m)eter/' => '$1etre', ); $htmlString = "<p><span style='color:red'>The color of the sky is: gray</p>"; $doc = new DOMDocument(); $doc->loadHtml($htmlString); process($doc, $replaceRules); $string = $doc->saveHTML(); echo mb_substr($string,119,-15);
Он работает нормально, но он терпит неудачу (поскольку дочерний узел заменен на первый экземпляр), если html имеет текст и HTML. Поэтому он работает
<div>The distance is four kilometers</div>
но нет
<div>The distance is four kilometers<br>1000 meters to a kilometer</div>
или
<div>The distance is four kilometers<div class="guide">1000 meters to a kilometer</div></div>
Любые идеи метода, который будет работать на таких примерах?
Вызов $node->replaceChild
приведет к $node->childNodes
итератора $node->childNodes
. Сначала вы можете получить дочерние узлы, а затем обработать их:
function process($node, $replaceRules) { if($node->hasChildNodes()) { $nodes = array(); foreach ($node->childNodes as $childNode) { $nodes[] = $childNode; } foreach ($nodes as $childNode) { if ($childNode instanceof DOMText) { $text = preg_replace( array_keys($replaceRules), array_values($replaceRules), $childNode->wholeText); $node->replaceChild(new DOMText($text),$childNode); } else { process($childNode, $replaceRules); } } } }