Очевидно, что прямая обрезка строки не подходит для вашего второго изображения:
...
<figure>
<img class="aligncenter" src="http://brickhut.files.wordpress.com/2011/05/theempirestrikesback1.jpg" alt="" width="540" height="800" />
<figcaption></figcaption>
</figure>
Обрезка после того, как изображение оставит незакрытые элементы:
...
<figure>
<img class="aligncenter" src="http://brickhut.files.wordpress.com/2011/05/theempirestrikesback1.jpg" alt="" width="540" height="800" />
Что может нарушить рендерингстраница внутри браузера.И это не играет роли, если вы используете preg_match
с регулярным выражением здесь или некоторыми строковыми функциями.
Вам нужен DOM-парсер, такой как DOMDocument
, который способенобработать HTML:
Учитывая некоторый пример HTML-кода, который похож на ваш вопрос:
$html = <<<HTML
dolor sit amet, consectetuer adipiscing elit. <img src="http://example.com/img-a.jpg"> Aenean commodo
ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes,
nascetur ridiculus mus.
<figure>
<img src="http://example.com/img-b.jpg">
<figcaption>Figure Caption</figcaption>
</figure>
Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut.
HTML;
Теперь вы можете использовать класс DOMDocument
для загрузки фрагмента HTML внутри <body>
тег - потому что это все ваше тело HTML для манипуляции.Поскольку вы используете нестандартные теги HTML (<figure>
& <figcaption>
), вы должны отключить предупреждения о них при загрузке строки с помощью libxml_use_internal_errors
:
$doc = new DOMDocument();
libxml_use_internal_errors(1);
$doc->loadHTML(sprintf('<body>%s</body>', $html));
Этобазовая настройка парсера DOM, теперь ваш HTML находится внутри парсера.Теперь начинается интересная часть.Вы хотите создать отрывок до второго изображения документа.Это означает, что все после этого элемента должно быть удалено.Звучит так же просто, как вырезать строку, которая, как мы знаем, не работает, но на этот раз анализатор DOM выполняет всю работу за нас.
Вам нужно только получить все узлы (<tag>
, Text, <!-- comments -->
, ...) и удалите их.Все узлы после второго тега <img>
в ( после порядка документов).Такие вещи можно выразить с помощью XPath :
/descendant::img[position()=2]/following::node()
Парсер DOM PHP поставляется с XPath, поэтому давайте сделаем это:
$xp = new DOMXPath($doc);
$delete = $xp->query('/descendant::img[position()=2]/following::node()');
foreach ($delete as $node)
{
$node->parentNode->removeChild($node);
}
Осталось толькополучить (примерный вывод) оставшуюся выдержку.Как мы знаем, это все внутри тега <body>
:
foreach ($doc->getElementsByTagName('body')->item(0)->childNodes as $child)
{
echo $doc->saveHTML($child);
}
, что даст вам следующее:
dolor sit amet, consectetuer adipiscing elit. <img src="http://example.com/img-a.jpg"> Aenean commodo
ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes,
nascetur ridiculus mus.
<figure><img src="http://example.com/img-b.jpg"></figure>
Как показывает этот пример, тег <figure>
правильно закрытсейчас.
Аналогичный сценарий заключается в создании выдержки после определенной длины текста или числа слов: перенос слов / вырезание текста в строке HTML