考虑以下PHP代码
<?php
$html_data =
'<html><body>
<ol>
<li><strong>Question 1</strong> Answer1</li>
<li><strong>Question 2</strong> Answer2</li>
</ol></body></html>';
$doc = new DOMDocument();
$doc->loadHTML($html_data);
$xpath = new DOMXPath($doc);
$ols = $xpath->query('//ol');
$ol = $ols->item(0);
$lis = $ol->childNodes;
foreach ($lis as $li) {
echo $li->firstChild->nodeValue."<br />";
echo $li->lastChild->nodeValue."<br />";
//echo $li->childNodes->item(0)->nodeValue."<br />";
}
?>
如果我删除此代码最后一行的注释并访问childNodes DOM Object Array,我的foreach循环只执行一次。但是,如果我使用firstChild和lastChild访问相同的元素,如上所示,我可以成功迭代所有'li'标签。
我根本无法理解这一点。这是PHP中的错误吗?
答案 0 :(得分:1)
我尝试使用以下代码重现您的问题(在PHP 5.3.14上):
Interactive shell
php > $xml = <<<XML
<<< > <root>
<<< > <ol>
<<< > <li><strong>Question 1</strong> Answer1</li>
<<< > <li><strong>Question 2</strong> Answer2</li>
<<< > </ol>
<<< > </root>
<<< > XML;
php > $doc = new DOMDocument();
php > $doc->loadXML($xml);
php > $xpath = new DOMXPath($doc);
php > $ols = $xpath->query('//ol');
php > $ol = $ols->item(0);
php > $lis = $xpath->query('//li', $ol);
php > foreach ($lis as $li) {
php { echo $li->firstChild->nodeValue."<br />";
php { echo $li->lastChild->nodeValue."<br />";
php { echo $li->childNodes->item(0)->nodeValue."<br />";
php { }
Question 1<br /> Answer1<br />
Question 1<br />
Question 2<br /> Answer2<br />
Question 2<br />
如你所见,我没有成功,一切正常。我唯一改变的是$lis = $ol->childNodes;
到$lis = $xpath->query('//li', $ol);
,因为否则我在<li>
个节点之间得到了空白文本节点,并且脚本崩溃了。
答案 1 :(得分:1)
如果你不压抑你的错误报告,你会发现你有一个致命错误会破坏你的脚本。
要使用项方法:
foreach ($lis as $li) {
if (method_exists($li->childNodes, 'item')) {
echo $li->childNodes->item(0)->nodeValue."<br />";
// To reproduce the exact output you need this line also.
// You need to display the second child (Answer)
echo $li->childNodes->item(1)->nodeValue."<br />";
}
}
唯一不同的是第一个脚本
foreach ($lis as $li) {
echo $li->firstChild->nodeValue."<br />";
echo $li->lastChild->nodeValue."<br />";
//echo $li->childNodes->item(0)->nodeValue."<br />";
}
仅抛出注意:尝试获取非对象的属性,但脚本会继续。
与方法项()一样,它会引发致命错误。 (致命错误:调用非对象上的成员函数项()。会杀死您的脚本。
有关如何迭代这些nodesList(foreach与for)的更多详细信息,请阅读这些页面中的注释
由于<li>
标记之后的尾随空格,您尤其遇到此问题。
它循环如下:第一个<li>
标记,然后是空格' ' DOMText
元素,然后是第二个<li>
标记,然后是第二个' ' DOMText
元素。
在DOMText元素上它崩溃了。你可以清理空格,它会起作用。
$html_data = '<html><body><ol><li><strong>Question 1</strong> Answer1</li><li><strong>Question 2</strong> Answer2</li></ol></body></html>';