问题
I have this HTML string in a DOMElement
:
<h1>Home</h1>
test{{test}}
I want to replace this content in a way that only
<h1>Home</h1>
test
remains (so I want to remove the {{test}}
).
At this moment, my code looks like this:
$node->nodeValue = preg_replace(
'/(?<replaceable>{{([a-z0-9_]+)}})/mi', '' , $node->nodeValue);
This doesn't work because nodeValue
doesn't contain the HTML value of the node.
I can't figure out how to get the HTML string of the node other than using $node->C14N()
, but by using C14N
I can't replace the content.
Any ideas how I can remove the {{test}}
in an HTML string like this?
回答1:
Have you tried the DOMDocument::saveXML
function? (http://php.net/manual/en/domdocument.savexml.php)
It has a second argument $node
with which you can specify which node to print the HTML/XML of.
So, for example:
<?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);
?>
This will give you:
<body>
<h1>Home</h1>
test{{test}}
</body>
If you do not want the <body>
tag, you could cycle through all of its childnodes:
<?php
foreach($root->childNodes as $child){
echo $doc->saveXML($child);
}
?>
This will give you:
<h1>Home</h1>test{{test}}
Edit: you can then of course replace {{test}}
by the regex that you are already using:
<?php
$xml = '';
foreach($root->childNodes as $child){
$xml .= preg_replace(
'/(?<replaceable>{{([a-z0-9_]+)}})/mi', '',
$doc->saveXML($child)
);
}
?>
This will give you:
<h1>Home</h1>test
Note: I haven't tested the code, but this should give you the general idea.
回答2:
The issue is mainly around how you navigate the DOM but there's also an issue with your RegExp; XPath actually provides a lot of flexibility when it comes to DOM manipulation so that's my preferred solution.
Assuming you have a DOMDocument built like this (I've attached an 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);
You can specifically target the text node of that <div>
with '/div/text()'
in XPath.
So to replace {{test}}
within that text node without corrupting the rest of the node, you would do:
$xpath->query('/div/text()')->item(0)->nodeValue = preg_replace(
'/(.*){{[^}]+}}/m',
'$1',
$xpath->query('/div/text()')->item(0)->nodeValue
);
Somewhat convoluted but the output from $dom->saveXML();
is:
<?xml version="1.0" encoding="utf-8"?>
<div><h1>Home</h1>test</div>
{{test}}
has been removed leaving the rest intact.
来源:https://stackoverflow.com/questions/37964378/domelement-replace-html-value