Оберните тег H3 и все теги UL под ним в div - PullRequest
0 голосов
/ 08 марта 2019

У меня есть структура, которая выглядит следующим образом:

<h3><span class="header" id="first_set">My Heading</span></h3>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<h3><span class="header" id="second_set">My Second Heading</span></h3>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<h3><span class="header" id="third_set">My Third Heading</span></h3>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>

Я извлек это из веб-страницы, используя DOMDocument .Мне нужно перебрать 9000 страниц, которые имеют небольшие различия в них.Таким образом, «третий заголовок» может фактически быть таблицей в некоторых случаях вместо другого h3.

То, что я пытаюсь сделать точно, - это обернуть div вокруг второго заголовка и закрыть div, когда он больше не находит</ul> тегов (так что пока не попадет что-либо, что не является тегом ul ).Таким образом, результат будет примерно таким:

<h3><span class="header" id="first_set">My Heading</span></h3>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<div class="second_heading">
<h3><span class="header" id="second_set">My Second Heading</span></h3>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
</div>
<h3><span class="header" id="third_set">My Third Heading</span></h3>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>
<ul><li>Text Text Text</li></ul>

Я думаю preg_replace, но не уверен, как сделать логику "close div, когда найден последний закрывающий тег ul".

1 Ответ

1 голос
/ 08 марта 2019

Вы можете достичь этого, продолжая работать с вашим DOMDocument.Я предполагаю, что у вас есть переменная с именем $node, которая является узлом над HTML, который вы показываете в своем вопросе.В этом случае вы можете найти все дочерние узлы этого элемента, используя DOMXPath, затем итерировать их, пока не дойдете до второго <h3>, и добавить этот и все последующие элементы <ul> к новому <div> до тех пор, покадобраться до первого элемента не <ul> после второго заголовка:

$div = $doc->createElement('div');
$xpath = new DOMXPath($doc);
$headers = 0;
foreach ($xpath->query('./*', $node) as $child) {
    echo $child->nodeName;
    switch ($child->nodeName) {
        case 'h3':
            $headers++;
            if ($headers == 2) {
                $node->replaceChild($div, $child);
                $div->appendChild($child);
            }
            else if ($headers == 3) {
                break 2;
            }
            break;
        case 'ul':
            if ($headers == 2) $div->appendChild($child);
            break;
        default:
            // if a non-ul element after the 2nd header, exit the loop
            if ($headers == 2) break 2;
            break;
    }
}

Демонстрация на 3v4l.org

...