我在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服务器安装上运行它。
有人能解释我发生了什么吗?
谢谢!
答案 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。