Почему этот код DOMDocument не работает при попытке переставить элементы? - PullRequest
0 голосов
/ 09 марта 2011

Я пытаюсь получить HTML в этом шаблоне ...

<p>a</p>
<p>b</p>
<p>c</p>
...
<h3>title</h3>

<p>e</p>
<p>e</p>
<p>f</p>
...
<h3>title2</h3>
...

... и превратить его в ...

<ul>
  <li>
     <blockquote>
        <p>a</p>
        <p>b</p>
        <p>c</p>
        <cite>title</cite>
     </blockquote>
  </li>
  <li>
     <blockquote>
        <p>d</p>
        <p>e</p>
        <p>f</p>
        <cite>title2</cite>
     </blockquote>
  </li>
</ul>

У меня есть PHP-код...

$dom = new DOMDocument('1.0', 'utf-8');

$dom->preserveWhiteSpace = FALSE;

$dom->loadHTML($content);

$ul = $dom->createElement('ul');

$body = $dom->getElementsByTagName('body')->item(0);

$blockquote = FALSE;

foreach($body->childNodes as $element) {

    if ($element->nodeType != XML_ELEMENT_NODE) {
        continue;
    }

    if ( ! $blockquote) {
        $blockquote = $dom->createElement('blockquote');
        $li = $dom->createElement('li');
    }

    switch ($element->nodeName) {

        case 'p':
            $blockquote->appendChild($element);

            break;
        case 'h3':
            $li->appendChild($blockquote);

            $ul->appendChild($li);

            $blockquote = $li = FALSE;
            break;

    }
}

$body->appendChild($ul); 
echo $dom->saveHTML();

Хотя функциональность не была закончена, я заметил, что цикл остановился, когда я добавил $blockquote->appendChild($element).

Если я удаляю все вещи appendChild, цикл работаетхорошо.

Я предполагаю, что, перемещая текущий элемент в итерации, он прерывает цикл.

Как бы заставить это работать?

Ответы [ 2 ]

1 голос
/ 09 марта 2011

Ваше предположение верно.Поскольку childNodes отражает текущий DOM, перемещение элементов таким образом, как вы делаете, приводит в замешательство цикл.

Одна из техник, которую я успешно использовал в прошлом (хотя я никогда не пробовал ее с php), заключается в циклическом переходедочерние узлы в обратном порядке.Поскольку вы добавляете узлы в конец списка childNodes, это означает, что вы всегда работаете с элементом, который не был перемещен с момента запуска цикла.

Очевидно, вам нужно изменить ul/ li / логика построения blockquote немного, чтобы учесть обработку в обратном порядке.

1 голос
/ 09 марта 2011

Если при вставке в текущий документ он задыхается, задумывались ли вы о создании нового документа? Вы можете использовать метод importNode в DOMDocument, чтобы скопировать только правильные биты из старого документа в правильную структуру, которую вы создадите в новом документе.

Возможно, вы сможете использовать аналогичный прием, используя фрагмент документа , только используя сериализованный XML вместо работы с объектными узлами. Это может работать для тегов абзаца, по крайней мере.

...