如何用其中一个子p节点替换div

时间:2016-08-27 14:50:11

标签: php regex

我从Response获得的这个HTML。

我需要删除多余的文字。

以下内容有一行

<?php
    $str = <<<HTML
    AAAA <span>span txt</span>
    <div class='unique_div' id='xrz' data-id='1'>
        div text
        <span>span text</span>
        <p class='unique_p'>
            <span>p span text</span>
            <p>p p text</p>
        </p>
        div text
    </div>
    BBBB <span>span txt</span>
HTML;

如何替换里面的p上的div?

我需要编写一个正则表达式来获得以下结果

<?php
    $str = <<<HTML
    AAAA <span>span txt</span>
    <p class='unique_p'>
        <span>p span text</span>
        <p>p p text</p>
    </p>
    BBBB <span>span txt</span>
HTML;

只有一个div和p具有这样的属性。

1 个答案:

答案 0 :(得分:1)

由于您正在查看看似HTML的内容,并且鉴于您的要求需要对Document Object Model (DOM)进行某种形式的修改,我建议使用像DOMDocument这样的DOM解析器。

如果我正确理解了您的问题,那么您希望将具有<div>属性id的{​​{1}}节点替换为具有xrz节点的p节点类属性unique_pdiv 的子级。

  1. 获取div非常简单,因为它有id且它们是唯一的。因此,我们可以使用DOMDocument::getElementById之类的方法来获取div
  2. 让它的孩子p变得有点棘手,因为我们要确保它既是div的孩子又具有指定的类。因此,我们将使用XPath依赖DOMXPath查询。
  3. 最后,我们将使用DOMNode::replaceChild替换div与其捕获的孩子p
  4. 这是一个简单的例子。

    $str = <<<HTML
        AAAA <span>span txt</span>
        <div class='unique_div' id='xrz' data-id='1'>
            div text
            <span>span text</span>
            <p class='unique_p'>
                <span>p span text</span>
                <p>p p text</p>
            </p>
            div text
        </div>
        BBBB <span>span txt</span>
    HTML;
    
    libxml_use_internal_errors(true);
    $dom = new DOMDocument;
    $dom->loadHTML($str, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
    $xpath = new DOMXPath($dom);
    $children = $xpath->query('//div/p[@class="unique_p"]');
    $p = $children->item(0);
    $div = $dom->getElementById('xrz');
    $div->parentNode->replaceChild($p, $div);
    echo $dom->saveHTML();
    

    输出看起来应该是这样的。

    <p>AAAA <span>span txt</span>
        <p class="unique_p">
                <span>p span text</span>
                </p><p>
        BBBB <span>span txt</span></p></p>
    

    如果您想知道为什么输出可能与您预期的略有不同,请务必注意您的问题中提供的初始HTML实际上是格式错误。

    See section 9.3.1 of the HTML 4.01 specification

      

    P元素代表一个段落。它不能包含块级元素(包括P本身)。

    因此,每当DOM解析器在另一个p标记内找到一个开放的p标记时,它就会先隐式关闭前一个标记。