【问题标题】:Can't understand how to use PHP DOMDocument::getElementById不明白如何使用 PHP DOMDocument::getElementById
【发布时间】:2014-12-28 04:32:39
【问题描述】:

我用 PHP 编写了这个小测试代码,试图掌握 DOMDocument::getElementById 的工作原理。我这样写是为了可以使用方法链。

<?php
class SMHtmlElement extends DOMElement {

    public function __construct($name, $value = NULL, $namespaceURI = NULL) {
        parent::__construct($name, $value, $namespaceURI);
    }

    public function attr($attribute, $value) {
        if (!empty($attribute)) {
            $this->setAttribute($attribute, $value);
        }
        return $this;
    }

    public function id($value) {
        $this->attr('id', $value);

        // this doesn't helped.
        @$this->ownerDocument->validate();

        $this->setIdAttribute('id',TRUE);
        return $this;
    }
}

class SMHtmlDocument extends DOMDocument {

    private $body;

    public function __construct() {
        parent::__construct("1.0", "UTF-8");
        $this->validateOnParse = true;
        $this->loadHTML('<!DOCTYPE html><html><head></head><body></body></html>');
        $this->body = $this->getElementsByTagName('body')->item(0);
    }

    public final function bodyAdd($element, $beforeElement = NULL) {
        $el = new SMHtmlElement($element);
        if ($beforeElement)
            $beforeElement->insertBefore($el);
        else
            $this->body->appendChild($el);

        return $el;
    }
}

// this search should work it didn't
$dom = new SMHtmlDocument();
$p1 = $dom->bodyAdd('p')->id('foo');
$p = $dom->getElementById('foo');
echo $dom->saveHTML();
var_dump($p);

// when set the ID outside the method, it works.
$p2 = $dom->getElementsByTagName('p')->item(0);
$p2->setIdAttribute('id',true);
$p = $dom->getElementById('foo');
var_dump($p);

// let's see if both paragraph elements are the same
var_dump($p1->isSameNode($p2));
?>

执行之后,我得到了这样的输出:

$> php teste.php
<!DOCTYPE html>
<html><head></head><body><p id="foo"></p></body></html>
NULL // first var_dump()
object(DOMElement)#4 (0) { // second var_dump()
}
bool(true)

如您所见,我已在方法 id() 中将属性 id 标记为 ID,但它不起作用。但是当我在对象外部调用 setIdAttribute() 方法时,它确实起作用了。

这里的一些帖子建议使用 DTD,但是当我尝试生成 HTML5 时,据我所知,HTML5 不是基于 DTD。我也知道我可以使用 XPath 来找到我想要的 id,但我真的想了解为什么我的代码不能正常工作。

我在安装了 PHP 5.3 的 Ubuntu 12.04 服务器上运行它。

谁能解释一下发生了什么?

谢谢!

【问题讨论】:

    标签: php html dom


    【解决方案1】:

    我认为setIdAttribute 方法的行为非常奇怪。由于某些奇怪的原因,这个方法必须被调用偶数次。我不确定它在不同版本的 PHP 中是否一致。在我的情况下(5.5.13)这有效:

    版本 1:工作

    $dom = new SMHtmlDocument();
    $p1 = $dom->bodyAdd('p')->attr('id','foo');
    $p = $dom->getElementById('foo');
    echo $dom->saveHTML();
    var_dump($p);
    
    $p2 = $dom->getElementsByTagName('p')->item(0);
    $p = $dom->getElementById('foo');
    var_dump($p);
    
    // let's see if both paragraph elements are the same
    var_dump($p1->isSameNode($p2));
    

    这也有效:

    版本 2:工作

    $dom = new SMHtmlDocument();
    $p1 = $dom->bodyAdd('p')->attr('id','foo');
    $p1->setIdAttribute('id', TRUE);
    $p1->setIdAttribute('id', TRUE);
    $p = $dom->getElementById('foo');
    echo $dom->saveHTML();
    var_dump($p);
    
    $p2 = $dom->getElementsByTagName('p')->item(0);
    $p = $dom->getElementById('foo');
    var_dump($p);
    
    // let's see if both paragraph elements are the same
    var_dump($p1->isSameNode($p2));
    

    这不是:

    版本 3:损坏

    $dom = new SMHtmlDocument();
    $p1 = $dom->bodyAdd('p')->attr('id','foo');
    $p1->setIdAttribute('id', TRUE);
    $p = $dom->getElementById('foo');
    echo $dom->saveHTML();
    var_dump($p);
    
    $p2 = $dom->getElementsByTagName('p')->item(0);
    $p2->setIdAttribute('id', TRUE);
    $p2->setIdAttribute('id', TRUE);
    $p = $dom->getElementById('foo');
    var_dump($p);
    
    // let's see if both paragraph elements are the same
    var_dump($p1->isSameNode($p2));
    

    我认为这是底层xml库的错误,可能是libxml2。

    【讨论】:

    • 将 setIdAttribute() 加倍的好主意,尽管让事情变得更加奇怪。它也对我有用。但是,如果您添加第三个调用,它就会停止工作。所以当你说我们必须调用这个函数偶数次时你是对的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-09
    • 2012-11-17
    • 2012-10-25
    • 1970-01-01
    • 2011-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多