用URL更新DOMAttr值会导致参数丢失,除非使用htmlentities().为什么


Updating DOMAttr value with URL results in parameters being lost unless htmlentities() is used. Why?

我试图修改包含HTML的字符串中的链接,但我发现修改后的url缺少参数。

的例子:

$html = '
<p>
    <a href="http://example.com?foo=bar&bar=foobar">Example 1</a>
</p>';
libxml_use_internal_errors(true);
$dom = new 'DOMDocument();
$dom->loadHTML($html);
$xpath = new 'DOMXPath($dom);
foreach ($xpath->query('//a/@href') as $node) {
    echo '$node->nodeValue: ' . $node->nodeValue . PHP_EOL;
    $newValue = 'http://example2.com?foo=bar&bar=foobar';
    echo '$newValue: ' . $newValue . PHP_EOL;
    $node->nodeValue = $newValue;
    echo '$node->nodeValue: ' . $node->nodeValue . PHP_EOL;
}
输出:

$node->nodeValue: http://example.com?foo=bar&bar=foobar
$newValue: http://example2.com?foo=bar&bar=foobar
$node->nodeValue: http://example2.com?foo=bar

可以看到,在更新nodeValue之后,第二个参数丢失了。

在实验时,我尝试将$newValue更改为:

$newValue = htmlentities('http://example2.com?foo=bar&bar=foobar');

然后输出变成:

$node->nodeValue: http://example.com?foo=bar&bar=foobar
$newValue: http://example2.com?foo=bar&amp;bar=foobar
$node->nodeValue: http://example2.com?foo=bar&bar=foobar

为什么需要通过htmlentities()运行新的节点值

&号是XML/HTML中的保留字符-它们开始字符引用。如果您试图将它们直接写入DOM中的字符串,则通常会出现问题,因为DOM不知道您想说什么。当您首先使用htmlentities()时,它会对"&&quot;每个人都在说同一种语言。

幸运的是根本不需要htmlentities()。而不是直接设置nodeValue,使用setAttribute()方法的href的所有者。


而不是:

$node->nodeValue = $newValue;
使用

:

$node->ownerElement->setAttribute('href', $newValue);

直接操作DOM中的字符串可能会导致问题,这些问题甚至不一定在不同系统中表现相同。在你的例子中,我没有丢失参数,我丢失了整个URL。

我强烈建议尽可能使用setter