Рассмотрите этот HTML, усеянный любым пробелом или нерелевантными тегами, такими как div
а также span
:
<div>
<span><a href="#1">Title 1</a></span>
<p>Paragraph 2</p>
<p>Outside 3
<a href="#4">Title 4</a>
</p>
</div>
Как я могу преобразовать это в массив PHP пар ссылок и текста, в том же порядке, что и в HTML.
{"#1", "Title 1" },
{null, "Paragraph 2"},
{null, "Outside 3" },
{"#4", "Title 4" },
Проблема в том, что DOM ищет как $html->find("a, p")
захватит 4 дважды, один сам по себе и один раз внутри 3.
Мне интересно, если решение состоит в том, чтобы пройти документ «линейно», как человек будет читать элемент за элементом слева направо, и если узел имеет текст, вы берете родительский узел href
если есть.
Если это жизнеспособно, как вы можете легко пройти через DOM, как это? У кого-нибудь есть решение, желательно с Простой HTML DOM Parser или просто регулярное выражение, или встроенный PHP-фреймворк.
Я бы посмотрел на https://github.com/salathe/spl-examples/wiki/RecursiveDOMIterator Который поможет вам рекурсивно пересечь структуру дом.
$dom = new DOMDocument();
$dom->loadHTML('<html>'.$htmlString.'</html>'); // wrap your initial html in <html></html> since it has to be well-formed
$dit = new RecursiveIteratorIterator(new RecursiveDOMIterator($dom));
$result = array();
foreach ($dit as $node) {
unset($r);
if(trim($node->nodeValue) == "" || $node->childNodes->length > 0){ // we look only non-empty last level nodes
continue;
}
$parent = $node->parentNode;
if($parent->nodeName == 'a'){
$r[0] = $parent->getAttribute('href');
}
$r[1] = $node->nodeValue;
$result[] = $r;
}
Я нашел подход без DOM, обдумывая свой аккуратно организованный пример! Разбивая каждый тег на строки, я могу легко извлечь нужную информацию. Возможно, это не «правильно», но работает как задумано!
$array = preg_split("#(?=<)#", $html, 0, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach($array as $key => $item) {
preg_match('/>\s*(\S.*)/', $item, $m);
preg_match('/href="([^"]*)/', $item, $n);
}