2012-05-21 32 views
0

我知道一些similair问题已被问到,但我很喜欢卡在这里。我找不到任何好的教程来帮助我解决这个问题。但我想要做的应该是非常基本的。可以说,我要抢在Stackoverflow.com的H1“的常见问题”,使用Chrome得到的XPath我得到这个:回声Xpath与大教堂

//*[@id="h-top-questions"]

所以我的问题是;我现在如何回应这个?来自全国各地,我得到这个净使用的代码片段:

<?php 
$curl = curl_init('http://stackoverflow.com/'); 
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); 
curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.224 Safari/534.10'); 
$html = curl_exec($curl); 
curl_close($curl); 

if (!$html) { 
    die("something's wrong!"); 
} 

//var_dump(strlen($data)); 

$dom = new DOMDocument(); 
@$dom->loadHTML($html); 

$xpath = new DOMXPath($dom); 

$headerh1 = $xpath->query('//*[@id="h-top-questions"]'); 

foreach($headerh1 as $match) { 
    print_r($match);  
} 
?> 

我以为这只是将输出<h1 id="h-top-questions">Top Questions</h1>。但相反,我得到 DOMElement Object ( )

任何人都可以帮我吗?我正在努力学习这一点。

回答

1

您通过查询方法的结果得到一个DOMNodeList元素。 DOMNodeList 尝试通过item($ index)方法访问节点。

+1

我想我知道了,我把'print_r($ match);'改为'echo $ match-> nodeValue。 “\ n” 个;'。现在它起作用了,那是你的意思吗? – Linkjuice57

+0

是的,唯一的区别是您遍历节点来获取DOMNode而不是项目($ index)方法,但在这种情况下并不重要。 – erdeszt

0

为了以这种方式查看对象的内容,您需要将其转换为字符串。如果你想做到这一点,你可以或者简单echo/print它,或者将它转换为这样的字符串:

$string = (string) $object; 

当一个对象被转换成字符串,PHP调用它的__toString()方法。不幸的是,一个DOMElement对象没有定义,所以当你试图将其转换为字符串,您将收到以下错误:

Catchable fatal error: Object of class DOMElement could not be converted to string in...

在这种特定情况下,有一个穷人的解决办法,使一个做这是一个小数量的代码,那就是使用simplexml_import_dom()函数通过SimpleXML反弹 - 因为SimpleXMLElement类确实定义了一个asXML()方法,该方法会将其转换回XML字符串。所以,你可以这样做:

foreach($headerh1 as $match) { 
    $xml = simplexml_import_dom($match); 
    echo $xml->asXML(); 
} 

然而,在这种特定的情况下,这将导致以下的输出:

<h1 id="h-top-questions">&#13; 
     Top Questions &#13; 
    </h1> 

所以你看,有一些额外的HTML实体存在泄漏那些不在原始的源代码中。这发生在DOM和SimpleXML之间的某处。

为了解决这个问题,这将是可能的:

  • 通过html_entity_decode()传递的输出。这不是一个好的选择,因为它可能导致无效的XML/HTML输出。
  • 将您自己的函数转换为一个DOMElement字符串。这也不是一个好的选择,因为它会非常复杂,并且您可能需要通过多个级别进行递归才能成功检索完整的节点列表。

但是,这里要记住的一件事是,除了测试和调试之外,你所做的并没有太多的实际应用。一个人永远不会真的想输出一个部分文件。