PHP preg_match все, пока - PullRequest
       25

PHP preg_match все, пока

1 голос
/ 24 февраля 2012

У меня есть запись в блоге, которая иногда содержит много текста / изображений, и я хочу вырезать выдержку из этого блога.Чтобы быть более конкретным, я хочу сопоставить все до тех пор, пока после второго тега изображения

ниже не будет некоторый образец текста.

Я пробовал использовать негативные взгляды типа

/[\w\r\n;:',."&\s*<>=-_]+(?!<img)/i

но я не могу придумать, как применить предвкушение к модификатору «+».У кого-нибудь есть подсказка, я был бы очень благодарен.

*override*
I've been stuck in a room lately, and though it's hard to stay creative all the time,         sometimes you need that extra kick. Well for some us we have to throw pictures of true creative genius at ourselves to stimulate us.

So sit back and soak in some inspiration I've come across the past year.

&nbsp;

&nbsp;

&nbsp;

<figure>
    <a href="">
    <img class="aligncenter" src="http://funnypagenet.com/wp-content/uploads/2011/07/Talesandminimalism_12_www.funnypagenet.com_.jpg" alt="" width="574" height="838" />
    </a>
    <figcaption></figcaption>
</figure>

&nbsp;

&nbsp;

&nbsp;

&nbsp;
<h4 style="text-align: center;">
    <a href="http://funnypagenet.com/tales-and-minimalism/">source</a>
</h4>
Couldn't find who did this, but couldn't explain the movie any simpler

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

<figure>
    <img class="aligncenter" src="http://brickhut.files.wordpress.com/2011/05/theempirestrikesback1.jpg" alt="" width="540" height="800" />
    <figcaption></figcaption>
</figure>

&nbsp;

&nbsp;

&nbsp;

Ответы [ 3 ]

3 голосов
/ 25 февраля 2012

Очевидно, что прямая обрезка строки не подходит для вашего второго изображения:

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

1 голос
/ 24 февраля 2012

Ну, это не регулярное выражение, но оно должно работать:

$post = str_ireplace('<img', '!!!<img', $post);
list($p1, $p2) = explode('!!!', $post);
$keep = $p1 . $p2;

Помещает маркер разделения перед тегами изображения (!!!), разделяет их и сохраняет первые два фрагмента, которые должны быть всем до второго тега изображения. Не требуется регулярное выражение.

Редактировать: Поскольку это отрывок, вы можете запустить strip_tags() для результата. Возможно, что если вы этого не сделаете, у вас будут открытые теги HTML, которые никогда не закроются.

0 голосов
/ 24 февраля 2012

Если вам действительно нужно решение на основе регулярных выражений, то вот оно:

// assuming $str is your full HTML text
if ( preg_match_all('~^(.*?<img\s.*?<img\s[^>]*>)~si', $str, $m) )
    print_r ( $m[1] );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...