2011-10-24 78 views
2

我要寻找此功能:PHP的DOMDocument/XPath的:获取HTML文本和环绕标签

鉴于这是HTML页:

<body> 
<h1>Hello, 
    <b>world!</b> 
</h1> 
</body> 

我想只包含一个数组DISTINCT文本元素 (无重复)和包围文本元素标签的数组:

结果上述“HTML”将是一个阵列,其看起来像这样:

array => 
"Hello," surrounded by => "h1" and "body" 
"world!" surrounded by => "b", "h1" and "body" 

我alreday做到这一点:

$res=$xpath->query("//body//*/text()"); 

使我有不同的文本内容,但省略了HTML标签。

当我只是这样做:

$res=$xpath->query("//body//*"); 

我得到重复的文字,每一个标签星座:“世界”例如为:会出现3次, 一次为“身体”,一次为“h1”,一次为“b”,但我似乎无法获得文本实际重复的信息。只是检查重复的文本是 不够充分,因为重复的文本有时只是以前的文本的子串,或者网站 可能包含真正的重复文本,然后将丢弃这是错误的。

我该如何解决这个问题?

非常感谢!

托马斯

+0

我认为你需要为这个XQuery的。无论如何,在HTML上使用XML技术并不好。该html可能不是格式良好的,因此,你会得到解析错误。 –

+3

@AurelioDeRosa DOM可以解析破损的HTML – Gordon

+0

您还没有接受答案。你能否澄清你在回答中寻找什么,以及为什么给出的答案不能令你满意。 – Gordon

回答

1

在你的示例代码,$res=$xpath->query("//body//*/text()")DOMText节点的DOMNodeList。对于每个DOMText,可以通过parentNode属性访问包含元素。

+0

啊,好主意,我只是试过了,实际上我可以访问parentNode,所以我可以手动迭代所有“更高”的节点来获取周围的标签。唯一的缺点可能是性能。也许还有另一种方法可以在一次运行中完成,因此效率可能更高。但是,尽管如此,我想给你一个好主意,我现在要测试它,看看它的表现。 – Thomas

5

您可以在DOMText节点parentNodes迭代:

$dom = new DOMDocument; 
$dom->loadHTML($html); 
$xpath = new DOMXPath($dom); 
$textNodes = array(); 
foreach($xpath->query('/html/body//text()') as $i => $textNode) { 
    $textNodes[$i] = array(
     'text' => $textNode->nodeValue, 
     'parents' => array() 
    ); 
    for (
     $currentNode = $textNode->parentNode; 
     $currentNode->parentNode; 
     $currentNode = $currentNode->parentNode 
    ) { 
     $textNodes[$i]['parents'][] = $currentNode->nodeName; 
    } 
} 
print_r($textNodes); 

demo

注意loadHTML将增加隐含的元素,例如它将添加使用XPath时必须考虑的html和head元素。另外请注意,用于格式化的任何空格都被视为DOMText,因此您可能会获得比您期望的更多的元素。如果你只想要查询非空一个DOMText节点使用

/html/body//text()[normalize-space(.) != ""] 

demo

+0

哇,谢谢你编程的演示,它的作品!非常感谢,还有关于空白的进一步想法!非常感谢你的帮助和努力! – Thomas