简体   繁体   English

使用simple-html-dom将img移到父段之前

[英]Move img before parent paragraph using simple-html-dom

Kay I got really stuck on this one :/ Tried SimpleHTMLDom as mentioned in the title and DOMDocument so far.. The $html will come from CKEditor in my Processwire driven page, I made a textformatter to auto post-process the output. 到目前为止,我真的很喜欢这个:/尝试过SimpleHTMLDom,如标题和DOMDocument所述。.$ html将来自CKEditor在我的Processwire驱动页面中,我制作了一个textformatter来自动对输出进行后处理。

So this is the test data 这就是测试数据

<?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;

So here's my SimpleHTMLDom try 所以这是我的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();

Having only one img in the $html above and everything works as expected, but those two (or more) return duplicates. 上面的$ html中只有一个img,并且一切正常,但是这两个(或更多)返回重复项。

  1. issue, it changes the sort order, so the 130x100 image will be first. 问题,它会更改排序顺序,因此130x100图片将是第一个。 I know I'm prepending, but I don't know how to change it. 我知道我要假装,但不知道如何更改。 Tried to stuff all images in a variable so they stay in order, but then I don't know how to prepend it to the paragraph.. 试图将所有图像填充到变量中,以使它们保持顺序,但后来我不知道如何将其添加到段落中。

  2. and actually more important issue is about the duplicates, strange thing is, it prepends all images properly but it's only deleting the first img within the paragraph and that's true for any additional image, so with 3 it would keep the last two (as I said, 1 will work fine) 而且实际上更重要的问题是关于重复项,奇怪的是,它正确地准备了所有图像,但是只删除了该段中的第一个img,对于其他任何图像都是如此,因此使用3可以保留最后两个(如我所说的) ,1可以正常使用)

What am I doing wrong? 我究竟做错了什么?

This would probably be better in a separate question, but I wanted to show that I also tried DOMDocument but couldn't get insertBefore to work (at all) I tried different variations (uncommented in below code) 在一个单独的问题中这样做可能会更好,但是我想证明我也尝试了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();

If something is not well enough documented or asked please feel free to comment and I'll try to explain better :) 如果没有足够的文献记载或询问,请随时发表评论,我会尽力进行解释:)

Edit: The html (coming from wysiwyg as mentioned above) will sometimes hold images in the middle or end of a paragraph, might contain a single or multiple images (undefined number) and there will be more than one paragraph in that html 编辑:的html(如上所述来自wysiwyg)有时会在一个段落的中间或结尾保存图像,可能包含一个或多个图像(未定义的数字),并且该html中将有多个段落

EDIT: Should've included how I want the output to be 编辑:应该包括我希望输出是

So this is the input 这是输入

<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>

And this should be the result 这应该是结果

<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>

Sorry for not mentioning that those images should be wrapped in figures and then in a container..a single image wouldn't need an extra container but that's actually not important.. I tested with a full code..wrapping images in figure, adding figcaption where applicable and wrapped multiple figure in a div, everything work on an article with only single images, then I came across some html similar to the test data above on another article which results in the mentioned duplication..So I stripped down the code to see where the problem comes from with no luck..that's why I just added this simplyfied code in the question because I thought once this works the other one will work, too ;-) 抱歉没有提到这些图像应该先包裹在图形中然后放在容器中..单个图像不需要额外的容器,但这实际上并不重要..我用完整的代码进行了测试..在图中包裹图像,添加了figcaption在适用的情况下,将多个图形包装在一个div中,所有内容只在一个图像上起作用,而在另一篇文章中却遇到了类似于上面测试数据的html,这导致了重复。看看问题出在哪里没有运气..这就是为什么我只在问题中添加了这个简单的代码,因为我认为一旦这行得通,另一个人也将工作;-)

Hope it's more clear now?! 希望现在更清楚吗?

So here is the basic code which does the job as questioned 所以这是完成工作的基本代码

// 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();

But who's interested in the full plan I'm using this for should have a look at the Processwire Forums https://processwire.com/talk/topic/13471-better-ckeditor-image-insertion-at-least-for-me/ 但是对我正在使用的完整计划感兴趣的人应该看看Processwire论坛https://processwire.com/talk/topic/13471-better-ckeditor-image-insertion-at-least-for-me /

Updated example :-) 更新的示例:-)

<?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">${2}</div> ${1} ${4}${5}';
    $html2 = preg_replace($pattern, $replacement, $html);

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

It probably can be done in one regex, but here is my solution. 它可能可以在一个正则表达式中完成,但这是我的解决方案。 And you'll have to have some identification on those images for second run. 而且,您必须对这些图像进行一些标识才能进行第二次运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM