无法理解如何使用PHP DOMDocument :: getElementById

时间:2014-10-31 19:03:44

标签: php html5 dom

我在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服务器安装上运行它。

有人能解释我发生了什么吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

我认为这是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。