【问题标题】:How can I use XPath and DOM to replace a node/element in php?如何使用 XPath 和 DOM 替换 php 中的节点/元素?
【发布时间】:2011-06-04 14:33:41
【问题描述】:

假设我有以下 html

$html = '
<div class="website">
    <div>
        <div id="old_div">
            <p>some text</p>
            <p>some text</p>
            <p>some text</p>
            <p>some text</p>
            <div class="a class">
                <p>some text</p>
                <p>some text</p>
            </div>
        </div>
        <div id="another_div"></div>
    </div>
</div>
';

我想用以下内容替换#old_div

$replacement = '<div id="new_div">this is new</div>';

给出最终结果:

$html = '
<div class="website">
        <div>
            <div id="new_div">this is new</div>
            <div id="another_div"></div>
        </div>
    </div>
';

有没有一个简单的剪切和粘贴功能可以用 PHP 做到这一点?


感谢 Gordon 的帮助,最终的工作代码:

<?php

$html = <<< HTML
<div class="website">
    <div>
        <div id="old_div">
            <p>some text</p>
            <p>some text</p>
            <p>some text</p>
            <p>some text</p>
            <div class="a class">
                <p>some text</p>
                <p>some text</p>
            </div>
        </div>
        <div id="another_div"></div>
    </div>
</div>
HTML;

$dom = new DOMDocument;
$dom->loadXml($html); // use loadHTML if it's invalid XHTML

//create replacement
$replacement  = $dom->createDocumentFragment();
$replacement  ->appendXML('<div id="new_div">this is new</div>');

//make replacement
$xp = new DOMXPath($dom);
$oldNode = $xp->query('//div[@id="old_div"]')->item(0);
$oldNode->parentNode->replaceChild($replacement  , $oldNode);
//save html output
$new_html = $dom->saveXml($dom->documentElement);

echo $new_html;

?>

【问题讨论】:

标签: php dom xpath


【解决方案1】:

由于链接副本中的答案并不全面,我举个例子:

$dom = new DOMDocument;
$dom->loadXml($html); // use loadHTML if its invalid (X)HTML

// create the new element
$newNode = $dom->createElement('div', 'this is new');
$newNode->setAttribute('id', 'new_div');

// fetch and replace the old element
$oldNode = $dom->getElementById('old_div');
$oldNode->parentNode->replaceChild($newNode, $oldNode);

// print xml
echo $dom->saveXml($dom->documentElement);

从技术上讲,您不需要 XPath。但是,您的 libxml 版本可能无法对未验证的文档 (id attributes are special in XML) 执行 getElementById。在这种情况下,将对getElementById 的调用替换为

$xp = new DOMXPath($dom);
$oldNode = $xp->query('//div[@id="old_div"]')->item(0);

Demo on codepad


要创建一个带有子节点的$newNode,而不必一个一个地创建和附加元素,您可以这样做

$newNode = $dom->createDocumentFragment();
$newNode->appendXML('
<div id="new_div">
    <p>some other text</p>
    <p>some other text</p>
    <p>some other text</p>
    <p>some other text</p>
</div>
');

【讨论】:

  • @gordon Catchable fatal error: Argument 2 passed to DOMNode::replaceChild() must be an instance of DOMNode, null given in C:\wamp\www\gv2010\user_area\replacement-test.php on line 24 ?
  • @Gordon 太好了。我的示例背后的实际情况是 $replacement html 比单个节点复杂得多。有没有办法为$newNode 使用字符串(heredoc)?
  • @Gordon - 先生,您是绝对的传奇人物。
  • @Haroldo 我很愿意相信这一点,但不,我只知道我在 DOM 周围的方式以及其中的一些怪癖;)不客气。
【解决方案2】:

先使用 jquery hide() 隐藏特定的 div,然后使用 append 附加新的 div

$('#div-id').remove();
$('$div-id').append(' <div id="new_div">this is new</div>');

【讨论】:

  • 一个问题是关于 PHP(服务器端),而不是 javascript(客户端)。
  • 加上即使这是客户端,您的解决方案也是错误的,因为它是附加而不是替换,因此不会保留原样...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-11
  • 2018-03-25
  • 2010-10-25
  • 2015-08-18
  • 2011-07-05
  • 2010-11-10
相关资源
最近更新 更多