【问题标题】:xPath insert before and after - With DOM and PHPxPath 在前后插入 - 使用 DOM 和 PHP
【发布时间】:2011-01-11 18:04:03
【问题描述】:

我需要在 HTML 结构中添加一个类。

我的类被称为“container”,应该在

  • 之后开始(ul 的孩子及其类似物) ,而不是孙子),并且应该在同一元素关闭之前结束。

    我的整个代码如下所示:

    <?php
    $content = '
        <div class="sidebar-1">
            <ul>
                <li>
                    <h4>Title</h4>
                    <ul> 
                        <li><a href="http://www.test.com">Test</a></li> 
                        <li><a href="http://www.test.com">Test</a></li> 
                    </ul> 
                </li> 
                <li>
                    <p>Paragraf</p>
                </li> 
                <li>
                    <h4>New title</h4>
                    <ul> 
                        <li>Some text</li>
                        <li>Some text åäö</li>
                    </ul> 
                </li> 
            </ul>
        </div>
    ';
    
    $doc = new DOMDocument();
    $doc->loadHTML($content);
    $x = new DOMXPath($doc);
    
    $start_text = '<div class="container">';
    $end_text = '</div>';
    
    foreach($x->query('//div/ul/li') as $anchor)
    {
        $anchor->insertBefore(new DOMText($start_text),$anchor->firstChild);
    }
    echo $doc->saveXML($doc->getElementsByTagName('ul')->item(0));
    ?>
    

    只要我可以添加类开头但不能添加关闭元素,它就可以工作。这样做我也会得到奇怪的编码。我希望输出与输入的编码相同。

    结果应该是

        <div class="sidebar-1">
            <ul>
                <li>
                    <h4>Title</h4>
                    <div class="content">
                        <ul> 
                            <li><a href="http://www.test.com">Test</a></li> 
                            <li><a href="http://www.test.com">Test</a></li> 
                        </ul>
                    </div>
                </li> 
                <li>
                    <div class="content">
                        <p>Paragraf</p>
                    </div>
                </li> 
                <li>
                    <h4>New title</h4>
                    <div class="content">
                        <ul> 
                            <li>Some text</li>
                            <li>Some text åäö</li>
                        </ul> 
                    </div>
                </li> 
            </ul>
        </div>
    

【问题讨论】:

  • 这里有一个概念错误。您想将所有ul 的子元素嵌入到div 元素中,并使div 成为ul 的唯一子元素
  • 不,我想在 li 元素中添加 div 元素。我将结果 HTML 添加到我的帖子中。
  • 不是一个 XPath 问题。
  • 正确答案使用 DOMXPath,所以是的,这是一个 XPath 问题。
  • 不管它使用什么选择器:appendChildremoveChild DOM API 方法是答案的关键。

标签: php dom


【解决方案1】:

我找不到更优雅的方式来重新分配所有孩子,所以我想这可以。不过,我认为它可以满足您的需求。

(注意:代码已更新以反映 cmets 中的其他要求。)

$doc = new DOMDocument();
$doc->loadHTML($content);
$x = new DOMXPath($doc);

foreach($x->query('//div/ul/li') as $anchor)
{
    $container = $doc->importNode(new DOMElement('div'));
    $container->setAttribute('class', 'container');

    $next = $anchor->firstChild;
    while ($next !== NULL) {
        $curr = $next;
        $next = $curr->nextSibling;

        if (($curr->nodeName != 'h4')
            || ($curr->attributes === NULL)
            || ($curr->attributes->getNamedItem('class') === NULL)
            || !preg_match('#(^| )title( |$)#', $curr->attributes->getNamedItem('class')->nodeValue)
        ) {
            $container->appendChild($anchor->removeChild($curr));
        }
    }

    $anchor->appendChild($container);
}

至于字符编码,我已经搞砸了一段时间,这是一个棘手的问题。当您使用loadXML() 加载而不是loadHTML() 加载时,字符显示正确。有a workaround in the comments,但它并不漂亮。希望一些用户 cmet 将帮助您找到可用的解决方案。

【讨论】:

  • 很好的答案,但是我有点太快了,无法发布 HTML 结果应该如何。一个细节是错误的。与其在 /li 之后立即启动“容器”类,不如在 /h4 之后立即启动它。 (我编辑了我的帖子)结尾 /div 是正确的,就像在您的代码中一样。大/小东西要修复?非常遗憾。到目前为止,给了你 1 票。
  • 没问题。代码已更新,尽管它假定只有一个 h4。如果有多个h4s,它们都将被排除在容器之外并堆在顶部,因为容器div是最后附加的。请注意,我像链表一样遍历孩子。您不能简单地迭代 $anchor-&gt;childNodes,因为您会在迭代时更改节点,从而导致各种令人困惑的行为。
  • 它似乎按预期工作。关于多个h4问题的事情。是否可以通过向将要堆积的 h4 添加“标题”类来解决它?这样,与其他 h4 标签相比,标题 h4 将是唯一的。我的猜测是,唯一需要改变的是 if 语句?
  • 是的,你可以这样做。请参阅更新的代码。当您深入研究时,它必须检查以确保您将要操作的对象确实存在,以防止错误。另外,请注意,正则表达式仅检查“title”类的存在(在开头、中间或结尾),因为允许元素具有多个由空格分隔的类。
  • if 语句比我想象的要复杂,但它似乎有效。我已经用几个场景对其进行了测试,到目前为止没有发现任何错误。非常感谢您的帮助!
猜你喜欢
  • 2017-04-14
  • 1970-01-01
  • 2012-12-06
  • 2011-12-21
  • 1970-01-01
  • 2011-11-12
  • 1970-01-01
  • 1970-01-01
  • 2015-08-22
相关资源
最近更新 更多