У меня есть HTML-документ в виде строки
Я хочу найти ключевое слово в этом документе и выяснить, где оно появилось в документе
Я имею в виду, в какой теге это отображалось
он отображался в тегах H1, H2 или TITLE
скажем, мой документ
$string = "<html> <head> <title>bar , this is an example</title> </head> <body> <h1>latest news</h1> foo <strong>bar</strong> </body> </html>"; $arr = find_term("bar",$string); print_r($arr);
Я ожидаю, что результат будет таким
[0]=> title [1]=> strong
потому что «бар» появился один раз в теге TITLE и один раз в теге STRONG
Я знал, что это сложный вопрос, поэтому я спрашиваю, знает ли кто-нибудь ответ 🙂
благодаря
что я до сих пор
function find_term($term,$string){ $arr = explode($term, $string); return $arr; } $arr = find_term("bar",$string); print_r($arr);
теперь у нас есть массив, который имеет значение
Array ( [0] => <html> <head> <title> [1] => , this is an example</title> </head> <body> <h1>latest news</h1> foo <strong> [2] => </strong> </body> </html> )
вы можете видеть, что последний тег каждого элемента массива – это тег, который содержит «бар», но теперь вопрос заключается в том, как узнать последний тег, появляющийся в каждом элементе?
благодаря
Вы можете использовать DOMDocument и xpath для этого.
<?php $doc = new DOMDocument; $doc->loadhtml('<html> <head> <title>bar , this is an example</title> </head> <body> <h1>latest news</h1> foo <strong>bar</strong> <i>foobar</i> </body> </html>'); $xpath = new DOMXPath($doc); foreach($xpath->query('//*[contains(child::text(),"bar")]') as $e) { echo $e->tagName, "\n"; }
печать
title strong i
Обратите внимание на i-элемент. Он содержит foobar, а не как одно слово и соответствует запросу xpath. Таким образом, это решение может быть или не быть достаточным.
Я не программист php, но, как правило, если вы можете получить парсер html dom, это упростит работу. Найдите все текстовые узлы и найдите их для текстовой строки. Когда вы получите совпадение, просто получите имя родительского узла.
Без парсера для работы с ним есть две проблемы.
Если вы не используете xhtml, html не является xml. <br> – хороший пример того, что вам придется жестко оцифровать.
Во-вторых, следующая комбинация тегов должна рассматриваться как «<a> <b> бар <c> </ c> </a>». Это должно привести к ответу «a», а не «b» или «c».
Даже после того, как вы разместили строку «bar», вы не можете не просто найти следующий или предыдущий тег. Вместо этого вы должны установить счетчик 1 и начать обратное отслеживание. Когда вы сталкиваетесь с начальным тегом, вы уменьшаетесь на единицу, а когда вы сталкиваетесь с конечным тегом, вы увеличиваете на единицу. Когда счетчик опустится до 0, сохраните тег, в котором вы сейчас находитесь.
Наконец, существует также неверный html, такой как «<i> <b> bar </ i> </ b>". Я действительно не знаю, есть ли хороший способ справиться с этим.
я думаю, что нужно сначала,
разобрать html в массив,
найти функцию, которая делает это как: http://www.php.happycodings.com/Arrays/code35.html
или класс вроде: http://www.phpclasses.org/browse/package/5139.html
после этого поиска в этом массиве по циклу.
Следующий код будет работать большую часть времени. Он не будет уважать HTML-комментарии и может запутаться в цитированных строках (например, <img alt="<grin>" ...
), но не будет задыхаться от таких патологических случаев, как <i><b>foo</i>bar</b>
и даже дает разумный результат.
Он не замечает теги, такие как <?php>
, и не знает о пустых тегах, таких как: <br> or <input>
но будет игнорировать теги, например </br />
. Вы можете добавить логику, чтобы игнорировать пустые теги (img, hr, br, input и т. Д.).
Слово поиска окружено \ b (граница слова), поэтому foobar не сопоставляется.
$html = "<html> <head> <title>bar , this is an example</title> </head> <body class=3> <h1>latest news</h1> foo <strong>bar</strong> <br />bar <i>foobar</i> </body> </html>"; $search = 'bar'; preg_match_all('/(\<(\/?)(\w+).*?(\/?)\>)|(\b'.$search.'\b)/i', $html, $matches, PREG_SET_ORDER); $tags = array(); $found = array(); foreach ($matches as $m) { if ($m[2] == '/') { $n = array_search($m[3], $tags); if ($n !== false) array_splice($tags, $n, 1); } else if ($m[3] and !$m[4]) { array_unshift($tags, $m[3]); } else if ($m[5]){ $found[] = $tags[0]; } } print_r($found);
Он выводит (с дополнительным баром после тега <br />
)
Array ( [0] => title [1] => strong [2] => body )
Хм, это сложный вопрос.
Почему бы вам не искать в строке ключевое слово, помните позицию, где вы его нашли, а затем переходите через строку назад, пока не увидите первый «<», напишите это в свой массив, пока не увидите «>».