使用 simple-html-dom 在 parent 段之前移动 img

Move img before parent paragraph using simple-html-dom

凯,我真的被这个卡住了:/ 到目前为止,已尝试标题和 DOMDocument 中提到的 SimpleHTMLDom .. $html 将来自我的 Processwire 驱动页面中的 CKEditor,我制作了一个文本格式化程序来自动 post-process 输出。

这是测试数据

<?php
$html = <<<_DATA
    <p><img src="http://placehold.it/100x100"><img src="http://placehold.it/130x100">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam</p>
_DATA;

这是我的 SimpleHTMLDom 尝试

<?php
$dom = str_get_html($html);
$imgs = $dom->find('img');

foreach ($imgs as $img) {
    $i = $img->outertext;
    $img->outertext = '';
    $img->parent()->outertext = $i . $img->parent()->outertext;
}
echo $dom->save();
$dom->clear();

在上面的 $html 中只有一个 img,一切都按预期工作,但是那两个(或更多)return 重复。

  1. 问题,它更改了排序顺序,因此 130x100 图像将排在第一位。 我知道我在预先准备,但我不知道如何更改它。试图将所有图像填充到一个变量中,以便它们保持有序,但后来我不知道如何将它添加到段落中..

  2. 实际上更重要的问题是关于重复的,奇怪的是,它正确地预先添加了所有图像,但它只删除了段落中的第一个 img,对于任何其他图像都是如此,所以 3它会保留最后两个(正如我所说,1 可以正常工作)

我做错了什么?

这在一个单独的问题中可能会更好,但我想表明我也尝试过 DOMDocument 但无法让 insertBefore 工作(根本) 我尝试了不同的变体(在下面的代码中未注释)

<?php
include_once "./classes/SmartDOMDocument.class.php";
$dom = new SmartDOMDocument();
$dom->loadHTML($html);

$imgs = $dom->getElementsByTagName('img');

foreach ($imgs as $img) {
    $i = $dom->createElement('img');
    $i->src = $img->getAttribute('src');
    $img->parentNode->insertBefore($i, $img->parentNode);
    // $img->insertBefore($i, $img->parentNode);
    // $dom->insertBefore($i, $img->parentNode);
    $img->parentNode->removeChild($img);
}

echo $dom->saveHTMLExact();

如果有什么地方没有被充分记录或被问到,请随时发表评论,我会尽力解释得更好:)

编辑: html(来自上面提到的所见即所得)有时会在段落的中间或结尾包含图像,可能包含一个或多个images (undefined number) 并且其中会有多个段落 html

编辑: 应该包含我希望的输出方式

所以这是输入

<p>
    <img src="http://placehold.it/100x100">
    <img src="http://placehold.it/130x100">
    <img src="http://placehold.it/160x100">
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam
</p>

这应该是结果

<div class="inlineGallery">
    <figure><img src="http://placehold.it/100x100"></figure>
    <figure><img src="http://placehold.it/130x100"></figure>
    <figure><img src="http://placehold.it/160x100"></figure>
</div>
<p>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam
</p>

抱歉没有提到那些图像应该用数字包裹然后放在容器中..单个图像不需要额外的容器,但这实际上并不重要.. 我用完整的代码进行了测试..在图中包装图像,在适用的地方添加 figcaption 并将多个图包装在 div 中,所有内容都适用于只有单个图像的文章,然后我遇到了一些 html 类似的到另一篇文章上面的测试数据导致提到的重复..所以我剥离了代码以查看问题出在哪里没有运气..这就是为什么我只是在问题中添加了这个简单的代码因为我曾经想过这个有效,另一个也有效 ;-)

希望现在更清楚了?!

更新示例:-)

<?php
    $html = "asdasd <p><img class=\"wrap\" src=\"http://placehold.it/100x100\">    <img class=\"wrap\" src=\"http://placehold.it/130x100\">  <img class=\"wrap\" src=\"http://placehold.it/160x100\">    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam</p> asdasd    ";

    $pattern = '/(<p>)((<img [^>]+>\s*)+)(.+?)(<\/p>)/i';

    $replacement = '<div class="inlineGallery"></div>  ';
    $html2 = preg_replace($pattern, $replacement, $html);

    $pattern2 = '/(<img class=\"wrap\" [^>]+>)/i';
    $replacement2 = '<figure></figure>';
    echo preg_replace($pattern2, $replacement2, $html2);
?>

它可能可以在一个正则表达式中完成,但这是我的解决方案。对于第二个 运行,您必须对这些图像进行一些识别。

所以这是完成所问工作的基本代码

// turn double linebreaks into paragraphs <br><br> to </p><p>
$value = preg_replace('#(?:<br\s*/?>\s*?){2,}#', '</p><p>', $value);

$dom = str_get_html($value);

/* first getting all <p> */
$paragraphs = $dom->find('p');

foreach ($paragraphs as $p) {
    $imgs = $p->find('img');

    /* init gallery container */
    $gallery = "<div class='gallery'>";
    foreach  ($imgs as $img) {
        /* get the current image */
        $i = $img->outertext;
        /* wrap in link */
        $i = "<a href='Link'>$i</a>";
        /* append to gallery */
        $gallery .= $i;
        /* remove original image from paragraph */
        $img->outertext = '';
    }
    /* close new gallery */
    $gallery .= "</div>";
    /* remove unnecessary <br> */
    $newParagraph = trim(preg_replace( '#^\s*(?:<br\s?\/?>)*\s*|(?:<br\s?\/?>)*\s*$#', '', trim($p->innertext)));
    /* wrap tidied text into <p> */
    $newParagraph = "<p>$newParagraph</p>";
    /* replace old paragraph by gallery and new paragraph */
    $p->outertext = $gallery . $newParagraph;
}
// save dom to $value
$value = $dom->save();
// clear dom
$dom->clear();

但是谁对我使用它的完整计划感兴趣,应该看看 Processwire 论坛 https://processwire.com/talk/topic/13471-better-ckeditor-image-insertion-at-least-for-me/