php - 首先 getElementsByTagName() 返回 HTML 中的所有元素(奇怪的行为)

标签 php wordpress dom

我正在使用 PHP 来解析 Wordpress 提供给我的 HTML。

这是一个帖子的 PHP 返回我的 Wordpress:

<p>Test</p> 
<p>
    <img class="alignnone size-thumbnail wp-image-39" src="img.png"/>
</p> 
<p>Ok.</p>

这是我的解析函数(有调试):

function get_parsed_blog_post()
{
    $html = ob_wp_content(false);

    print_r(htmlspecialchars($html));
    echo '<hr/><hr/><hr/>';

    $parse = new DOMDocument();
    $parse->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

    $xpath = new DOMXpath($parse);
    $ps = $xpath->query('//p');

    foreach ($ps as $p) 
    {
        $imgs = $p->getElementsByTagName('img');

        print($imgs->length);
        echo '<br/>';

        if ($imgs->length > 0)
        {
            $p->setAttribute('class', 'image-content');

            foreach ($imgs as $img)
            {
                $img->removeAttribute('class');
            }
        }        
    }

    $htmlFinal = $parse->saveHTML();

    print_r(htmlspecialchars($htmlFinal));
    echo '<hr/><hr/><hr/>';

    return $htmlFinal;
}

此代码的目的是删除 Wordpress 添加到 <img> 的类s,并设置任何 <p>包含图像的类 image-content .

这会返回:

1
1
0
<p class="image-content">Test
<p class="image-content">
    <img src="img.png">
</p>
<p>Ok.</p></p>

不知何故,它包装了第一次出现的 <p>围绕我整个解析的帖子,导致第一个 <p>拥有 image-content错误地应用了类。为什么会这样?我该如何阻止它?

最佳答案

方法一

至于完全使用您的代码,我做了一些更改以使其正常工作。

如果你要打印出每个$p您将能够看到第一个元素将包含您所有的 HTML。最简单的解决方案是添加一个空白 <p>在你的 HTML 之前并在 foreach 时跳过它.

function get_parsed_blog_post()
{
    $page_content_html = ob_wp_content(false);
    $html = "<p></p>".$page_content_html;
    print_r(htmlspecialchars($html));
    echo '<hr/><hr/><hr/>';

    $parse = new DOMDocument();
    $parse->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

    $xpath = new DOMXpath($parse);
    $ps = $xpath->query('//p');
    $i = 0;
    foreach ($ps as $p) 
    {
        if($i != 0) {
            $imgs = $p->getElementsByTagName('img');

            print($imgs->length);
            echo '<br/>';

            if ($imgs->length > 0)
            {
                $p->setAttribute('class', 'image-content');

                foreach ($imgs as $img)
                {
                    $img->removeAttribute('class');
                }
            }
        }
        $i++;
    }

    $htmlFinal = $parse->saveHTML();

    print_r(htmlspecialchars($htmlFinal));             
    echo '<hr/><hr/><hr/>';

    return $htmlFinal;
}

Total execution time in seconds: 0.00034999847412109

方法二

问题是由 LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD 引起的(这也是第一个 <p> 作为父级),但是您可以在没有这个的情况下删除文档标签。所以,你可以在这里做:

function get_parsed_blog_post()
{
$page_content_html = ob_wp_content(false);
$doc = new DOMDocument();
$doc->loadHTML($page_content_html);
foreach($doc->getElementsByTagName('p') as $paragraph) {
    $imgs = $paragraph->getElementsByTagName('img');
    if ($imgs->length > 0)
    {
        $paragraph->setAttribute('class', 'image-content');

        foreach ($imgs as $img)
        {
            $img->removeAttribute('class');
        }
    }        
}


/* REMOVING DOCTYPE, HTML AND BODY TAGS */

// Removing DOCTYPE
$doc->removeChild($doc->doctype);

// Removing HTML tag
$doc->replaceChild($doc->firstChild->firstChild, $doc->firstChild);

// Removing Body Tag
$html = $doc->getElementsByTagName("body")->item(0);
$fragment = $doc->createDocumentFragment();
while ($html->childNodes->length > 0) {
    $fragment->appendChild($html->childNodes->item(0));
}
$html->parentNode->replaceChild($fragment, $html);

$htmlFinal = $doc->saveHTML();

print_r(htmlspecialchars($htmlFinal));             
echo '<hr/><hr/><hr/>';

return $htmlFinal;
}

Total execution time in seconds: 0.00026822090148926

关于php - 首先 getElementsByTagName() 返回 HTML 中的所有元素(奇怪的行为),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30949944/

相关文章:

javascript - 根据视口(viewport)高度动态添加内容到引用的 React 子级

php - 准备好的语句和转义

php - 我无法升级 WordPress

php - 如何汇总 WooCommerce 购物车中添加的产品 ID 的额外费用

javascript - 将对象从 Django 传递到 Javascript DOM

javascript - afterRender 用于 html 绑定(bind)

javascript - PHP:从数据列表中打印(循环困难)

php - 如何将 orderid/itemno 发送到 paypal 并返回 PayPal Express Checkout API

php - 控制 PHP Echo 语句的位置

html - 删除 WordPress 主题上的边距