html — используйте DOMXPath и функцию запроса переполнения стека

Есть следующий раздел HTML-кода:

<ul id="tree">
<li>
<a href="">first</a>
<ul>
<li><a href="">subfirst</a></li>
<li><a href="">subsecond</a></li>
<li><a href="">subthird</a></li>
</ul>
</li>
<li>
<a href="">second</a>
<ul>
<li><a href="">subfirst</a></li>
<li><a href="">subsecond</a></li>
<li><a href="">subthird</a></li>
</ul>
</li>
</ul>

Нужно разобрать этот HTML-код и получить следующий (используя DOMXPath :: query () и foreach ())

- first
-- subfirst
-- subsecond
-- subthird
- second
-- subfirst
-- subsecond
-- subthird

Часть кода:

$xpath = new \DOMXPath($html);
$catgs = $xpath->query('//*[@id="tree"]/li/a');
foreach ($catgs as $category) {
// first level
echo '- ' . mb_strtolower($category->nodeValue) . '<br>';

// second level
// don't know
}

Заранее спасибо!

0

Решение

Вот для чего DOMBLAZE:

/* DOMBLAZE */ $doc->registerNodeClass("DOMElement","DOMBLAZE"); class DOMBLAZE extends DOMElement{public function __invoke($expression) {return $this->xpath($expression);} function xpath($expression){$result=(new DOMXPath($this->ownerDocument))->evaluate($expression,$this);return($result instanceof DOMNodeList)?new IteratorIterator($result):$result;}}

$list = $doc->getElementById('tree');

foreach ($list('./li') as $item) {
echo '- ', $item('string(./a)'), "\n";
foreach ($item('./ul/li') as $subitem) {
echo '-- ', $subitem('string(./a)'), "\n";
}
}

Выход:

- first
-- subfirst
-- subsecond
-- subthird
- second
-- subfirst
-- subsecond
-- subthird

DOMBLAZE является FluentDOM для бедных.

2

Другие решения

Для второго уровня вы также можете использовать другой запрос:

$dom = new DOMDocument();
$dom->loadHTML($markup);
$xpath = new DOMXpath($dom);
$elements = $xpath->query('//ul[@id="tree"]/li');
foreach($elements as $el) {
$head = $xpath->query('./a', $el)->item(0)->nodeValue;
echo "- $head <br/>";
foreach($xpath->query('./ul/li/a', $el) as $sub) { // query the second level
echo '-- ' . $sub->nodeValue . '<br/>';
}
}

пример из

1

По вопросам рекламы [email protected]