解析WordPress文章内容

3
我需要绕过一个奇怪的布局,即使在规划阶段也感到无助。基本上,我需要将所有不是.gallery的内容分离出来,并将其放入一个<aside />中。最初,我考虑使用edit_post插件API的钩子创建一个插件,但后来决定不这样做,因为这种内容更改是特定于布局的,而我想保持一个干净的数据库。所以... 如何解析WP的the_content以获取不是.gallery的内容?承认自己不是PHP专家,所以非常感谢帮助!
根据Michael在下面的评论,这里有一个WordPress的the_content类输出的示例:
HTML
<div class="entry-content">
    <div class="gallery">
        <dl class="gallery-item">
            <dt class="gallery-icon portrait">
                <img src="/imagePath/etc.jpg" class="attachment-thumbnail">
            </dt>
        </dl>
        <dl class="gallery-item">
            <dt class="gallery-icon portrait">
                <img src="/imagePath/etc.jpg" class="attachment-thumbnail">
            </dt>
        </dl>
        <dl class="gallery-item">
            <dt class="gallery-icon portrait">
                <img src="/imagePath/etc.jpg" class="attachment-thumbnail">
            </dt>
        </dl>
    </div>
    <p>Curabitur vulputate, ligula lacinia scelerisque tempor, lacus lacus ornare ante, ac egestas est urna sit amet arcu. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed molestie augue sit amet.</p>
    <ul>
        <li>Item A</li>
        <li>Item B</li>
        <li>Item C</li>
    </ul>
</div>

期望输出

<div class="entry-content">
    <div class="gallery">
        <dl class="gallery-item">
            <dt class="gallery-icon portrait">
                <img src="/imagePath/etc.jpg" class="attachment-thumbnail">
            </dt>
        </dl>
        <dl class="gallery-item">
            <dt class="gallery-icon portrait">
                <img src="/imagePath/etc.jpg" class="attachment-thumbnail">
            </dt>
        </dl>
        <dl class="gallery-item">
            <dt class="gallery-icon portrait">
                <img src="/imagePath/etc.jpg" class="attachment-thumbnail">
            </dt>
        </dl>
    </div>
    <aside>
        <p>Curabitur vulputate, ligula lacinia scelerisque tempor, lacus lacus ornare ante, ac egestas est urna sit amet arcu. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed molestie augue sit amet.</p>
        <ul>
            <li>Item A</li>
            <li>Item B</li>
            <li>Item C</li>
        </ul>
    </aside>
</div>

对于那些不熟悉 WP 类和标记布局的人,你能否发布一个示例,展示现在的标记是什么样子,以及你想要它看起来像什么?你真的需要更改标记吗?难道你不能仅通过 CSS 实现你想要的效果吗? - Michael Berkowski
谢谢Michael。我已经在上面包含了一个输出示例。不幸的是,出于各种原因,我确实需要更改标记。虽然我希望它可以使用CSS,这绝对是我的长项。 - technopeasant
1
有点粗俗,但你可以用jQuery/JavaScript来实现这个功能 - 参见https://dev59.com/KW_Xa4cB1Zd3GeqP37Jq - ggdx
1
是的,在JavaScript中很容易实现,但并不是最理想的选择。 - technopeasant
2个回答

6

您需要使用DOM解析器。以下是一个使用您的标记示例的实现方式。测试结果符合预期,希望这将为您提供所需的起点:

add_filter( 'the_content', 'wrap_nongallery_aside', 20 );
function wrap_nongallery_aside($content){
    $dom = new DOMDocument();
    $dom->loadHTML($content); // Replace with Edit below if PHP >= 5.4
    $aside = $dom->createElement('aside');
    $xpath = new DOMXPath($dom);
    $not_gallery = $xpath->query('//div[@class="entry-content"]/*[not(contains(@class, "gallery"))]');

    foreach($not_gallery as $ng){
        $aside->appendChild($ng);
    }
    $dom->getElementsByTagName('div')->item(0)->appendChild($aside);
    return $dom->saveHTML();
}

编辑:

如果你使用的是 PHP 版本大于等于 5.4,则可以通过以下方式轻松地从生成的标记中移除任何额外的 <html><body> 标签:

$dom->loadHTML($content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);


谢谢,这正是我所寻找的,而且非常清晰,超出了我的理解范围。 - technopeasant
值得注意的是,此方法添加了Doctype字符串和<html>和<body>标签,您可能不需要这些。 - Andreas Riedmüller
1
@AndreasRiedmüller 您说得对,但是在这个答案发布的8年中,还提供了关闭该行为的选项。有关详细信息,请参见此答案。 - maiorano84

1

Maiorano84的回答非常成功,但在他回答之前,我想出了一种针对我的情况不那么具体的备选方法,所以我认为分享一下会很好。

最初我打算放弃插件方法,因为它需要更改帖子内容本身 - 不仅是输出格式,而是意识到插件独立于主题安装。以下是一个非常简单、面向开发人员的插件,将[aside /]短代码转换为HTML元素。它完全基于 BSD Aside Sean D Burkin创建。我最终会在WP文本编辑器中包含一个按钮并将其开源。

<?php
/*
Plugin Name: RW Content Aside
Description: Inserts aside formatting into post content via shortcodes
Author: Daniel Redwood
Version: 0.1
Author URI: http://www.rdwd.fm/

Based on SBD Aside by Sean B. Durkin:
Original Plugin: http://seanbdurkin.id.au/pascaliburnus2/archives/51
Author: http://www.seanbdurkin.id.au
*/

if ( !is_admin() ){
  add_filter('the_content', 'handle_rw_aside');
}

function generate_random_str( $length=10)
{
  return substr(md5(rand()), 0, $length);
}

function generate_place_marker()
{
  return '@' . generate_random_str( 10) . '@';
}

function GetBody( $aside_instruction) {
  return preg_replace( '~^((<p>)?  \S+\s*=\s*.*?(<br \/>|<\/p>)\n?)*~mi', '', $aside_instruction);
}

function handle_rw_aside($the_content)
{
  $begin = generate_place_marker();
  $end   = generate_place_marker();

  $new_content = preg_replace(
    '~^((<p>)?\[aside\](<br />|</p>))(.*?)(^(<p>)?\[\/aside\](<br />|</p>))~ms',
    $begin . '$4' . $end,
    $the_content);

  $new_content = preg_replace_callback(
    '~^(<p>)?(!+\[\/?aside\])~m',
    function ($match) {
      return $match[1] . substr( $match[2], 1);
      },
    $new_content);

  $pattern = '~'.$begin.'(.*?)'.$end.'~s';

  return preg_replace_callback(
    $pattern,
    function ($match) {
      $aside_instruction = $match[1];
      $body = GetBody( $aside_instruction);
      $aside = '<aside class="contentAside">' . $body . '</aside>';
      return $aside;
      },
    $new_content);

}

?>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接