Не используйте regex для разбора HTML!
Да, в общем, использование regex для разбора HTML чревато опасностью.Специалисты по компьютерам правильно укажут, что HTML не является языком REGULAR .Однако, вопреки тому, что многие здесь считают, есть случаи, когда использование решения регулярных выражений совершенно правильно и уместно.Прочитайте сообщение Джеффа Этвудса в блоге на эту тему: Разбор HTML-кода Путь Ктулху .Оставив этот отказ в стороне, давайте продолжим с решением регулярных выражений ...
Повторное изложение проблемы:
Оригинальный вопрос довольно расплывчатый.Вот более точная (возможно, совсем не та, о которой просит ФП) интерпретация / переформулировка вопроса:
Дано: У нас есть некоторый текст HTML (либо HTML 4.01 *)1018 * или XHTML 1.0 ).Этот текст содержит <A..>...</A>
якорных элементов.Некоторые из этих элементов привязки являются ссылками на ресурс файла изображения (т. Е. Атрибут HREF
указывает на URI, заканчивающийся расширением файла: JPEG
, JPG
, PNG
или GIF
).Некоторые из этих ссылок на изображения представляют собой простые текстовые ссылки, где содержимое элемента привязки представляет собой простой текст, не имеющий других элементов HTML, например, <a href="picture.jpg">Link text with no HTML tags</a>
.
Найти: Есть лиРешение regex, которое будет принимать эти «обычные текстовые ссылки на изображения-ресурсы-файлы» и заменять текст ссылки элементом IMG
с атрибутом SRC
, установленным на то жеURI ресурса?Следующий (действительный HTML 4.01) пример ввода имеет три абзаца.Все ссылки в первом абзаце должны быть изменены, но все ссылки во втором и третьем абзацах НЕ должны быть изменены и оставлены как есть:
Пример ввода HTML:
<p title="Image links with plain text contents to be modified">
This is a <a href="img1.png">LINK 1</a> simple anchor link to image.
This <a title="<>" href="img2.jpg">LINK 2</a> has attributes before HREF.
This <a href="img3.gif" title='<>'>LINK 3</a> has attributes after HREF.
</p>
<p title="NON-image links with plain text contents NOT to be modified">
This is a <a href="tmp1.txt">LINK 1</a> simple anchor link to NON-image.
This <a title="<>" href="tmp2.txt">LINK 2</a> has attributes before HREF.
This <a href="tmp3.txt" title='<>'>LINK 3</a> has attributes after HREF.
</p>
<p title="Image links with NON-plain text contents NOT to be modified">
This is a <a href="img1.png"><b>BOLD 1</b></a> anchor link to image.
This is an <a href="img3.gif"><img src="img3.gif"/></a> image link to image.
</p>
Требуемый вывод HTML:
<p title="Image links with plain text contents to be modified">
This is a <a href="img1.png"><img src="img1.png" /></a> simple anchor link to image.
This <a title="<>" href="img2.jpg"><img src="img2.jpg" /></a> has attributes before HREF.
This <a href="img3.gif" title='<>'><img src="img3.gif" /></a> has attributes after HREF.
</p>
<p title="NON-image links with plain text contents NOT to be modified">
This is a <a href="tmp1.txt">LINK 1</a> simple anchor link to NON-image.
This <a title="<>" href="tmp2.txt">LINK 2</a> has attributes before HREF.
This <a href="tmp3.txt" title='<>'>LINK 3</a> has attributes after HREF.
</p>
<p title="Image links with NON-plain text contents NOT to be modified">
This is a <a href="img1.png"><b>BOLD 1</b></a> anchor link to image.
This is an <a href="img3.gif"><img src="img3.gif"/></a> image link to image.
</p>
Обратите внимание, что эти примеры включают тестовый пример <A..>...</A>
теги привязки имеют как одинарные, так и двойные кавычки как до, так и после желаемого атрибута HREF, и которые содержат соблазн cthulhu, (все же совершенно допустимый HTML 4.01), угловые скобки.
Обратите также внимание, что заменяющим текстом является (пустой) тег IMG, заканчивающийся: '/>'
(который НЕ является действительным HTML 4.01).Решение регулярного выражения:
Формулировка задачи определяет очень конкретный шаблон для сопоставления, который имеет следующие требования:
- Начальный тег
<A..>...</A>
может иметь любое количество атрибутов до и / или после атрибута HREF
. - Значение атрибута
HREF
должно иметь значение, заканчивающееся JPEG
, JPG
, PNG
или GIF
(дело-чувствителен). - Содержимое элемента
<A..>...</A>
не может содержать никаких других тегов HTML. - Целевой шаблон элемента
<A..>...</A>
НЕ является вложенной структурой.
При работе с такими высокоспециализированными подстроками, хорошо разработанное решение регулярных выражений может работать очень хорошо (с очень немногими крайними случаями, которые могут его сбить).Вот проверенная функция PHP, которая будет выполнять довольно хорошую работу (и правильно преобразовывать приведенный выше пример ввода):
// Convert text-only contents of image links to IMG element.
function textLinksToIMG($text) {
$re = '% # Match A element with image URL and text-only contents.
( # Begin $1: A element start tag.
<a # Start of A element start tag.
(?: # Zero or more attributes before HREF.
\s+ # Whitespace required before attribute.
(?!href\b) # Match attributes other than HREF.
[\w\-.:]+ # Attribute name (Non-HREF).
(?: # Attribute value is optional.
\s*=\s* # Attrib name and value separated by =.
(?: # Group for attrib value alternatives.
"[^"]*" # Either double quoted,
| \'[^\']*\' # or single quoted,
| [\w\-.:]+ # or unquoted value.
) # End group of value alternatives.
)? # Attribute value is optional.
)* # Zero or more attributes before HREF.
\s+ # Whitespace required before attribute.
href\s*=\s* # HREF attribute name.
(?| # Branch reset group for $2: HREF value.
"([^"]*)" # Either $2.1: double quoted,
| \'([^\']*)\' # or $2.2: single quoted,
| ([\w\-.:]+) # or $2.3: unquoted value.
) # End group of HREF value alternatives.
(?<= # Look behind to assert HREF value was...
jpeg[\'"] # either JPEG,
| jpg[\'"] # or JPG,
| png[\'"] # or PNG,
| gif[\'"] # or GIF,
) # End look behind assertion.
(?: # Zero or more attributes after HREF.
\s+ # Whitespace required before attribute.
[\w\-.:]+ # Attribute name.
(?: # Attribute value is optional.
\s*=\s* # Attrib name and value separated by =.
(?: # Group for attrib value alternatives.
"[^"]*" # Either double quoted,
| \'[^\']*\' # or single quoted,
| [\w\-.:]+ # or unquoted value.
) # End group of value alternatives.
)? # Attribute value is optional.
)* # Zero or more attributes after HREF.
\s* # Allow whitespace before closing >
> # End of A element start tag.
) # End $1: A element start tag.
([^<>]*) # $3: A element contents (text-only).
(</a\s*>) # $4: A element end tag.
%ix';
return preg_replace($re, '$1<img src="$2" />$4', $text);
}
Да, регулярное выражение в этом решении длинное, но это в основном из-за обширных комментариев, что также делает его очень читабельным .Он также правильно обрабатывает значения атрибутов в кавычках, которые могут содержать угловые скобки.Да, конечно, можно создать некоторую разметку HTML, которая нарушит это решение, но необходимый для этого код будет настолько запутанным, что его практически не услышат.