开发者

Why does this DOMDocument code not work when trying to rearrange elements?

开发者 https://www.devze.com 2023-02-16 04:01 出处:网络
I am trying to get HTML in this pattern... <p>a</p> <p>b</p> <p>c</p>

I am trying to get HTML in this pattern...

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

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

...and turn it into...

<ul>
  <li>
     <blockquote>
        <p>a</p>
        <p>b</p>开发者_如何学Go
        <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>

The PHP code I have is...

$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();

Whilst the functionality was not finished, I noticed that the loop stopped when I added $blockquote->appendChild($element).

If I remove all the appendChild stuff, the loop works fine.

My guess is that by moving the current element in the iteration, it breaks the loop.

How would I get this to work?


If it's choking when inserting into the current document, have you considered creating a new document instead? You can use the importNode method on DOMDocument to copy just the correct bits across from the old document into the right structure you'll create in the new document.

You might be able to use a similar trick using a document fragment, only using serialized XML instead of working with node objects. This could work for the paragraph tags, at least.


Your guess is correct. Because childNodes reflects the current DOM, moving elements in the way you are doing confuses the loop.

One technique I've used successfully in the past (though I've never tried it with php) is to loop through the childNodes in reverse order. Because you are appending nodes to the end of the childNodes list, it means that you are always working with an element that hasn't been moved since the loop started.

Obviously, you'll need to change the ul/li/blockquote construction logic a bit to allow for the reverse order processing.

0

精彩评论

暂无评论...
验证码 换一张
取 消