PHP DOMDocument / XPath: получить HTML-текст и окруженные теги - PullRequest
2 голосов
/ 24 октября 2011

Я ищу эту функциональность:

Имеется эта 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"

Я уже сделал это:

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

, который дает мне различное текстовое содержимое, но в котором отсутствуют html-теги.

Когда я просто делаю это:

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

Я получаю повторяющиеся тексты, одиндля каждого тега-созвездия: например: "мир!"будет отображаться 3 раза, один раз для "body", один раз для "h1" и один раз для "b", но я не могу получить информацию о том, какие тексты являются дубликатами.Одной проверки на наличие дублирующего текста недостаточно, поскольку дублирующие тексты иногда являются просто подстроками прежних текстов, или веб-сайт может содержать настоящий дубликат текста, который затем будет отброшен, что является неправильным.

Как я могу решить эту проблему?

Большое спасибо !!

Томас

Ответы [ 2 ]

5 голосов
/ 24 октября 2011

Вы можете выполнить итерацию по parentNodes DOMText узлов:

$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 добавит подразумеваемые элементы, например, добавит элементы html и head, которые вы должны будете учитывать при использовании XPath.Также обратите внимание, что любые пробелы, используемые для форматирования, считаются DOMText, поэтому вы, скорее всего, получите больше элементов, чем ожидаете.Если вы хотите запрашивать только непустые узлы DOMText, используйте

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

demo

1 голос
/ 24 октября 2011

В вашем примере кода $res=$xpath->query("//body//*/text()") - это DOMNodeList из DOMText узлов.Для каждого DOMText вы можете получить доступ к содержащему элементу через свойство parentNode.

...