Заменить строку между открывающим и закрывающим тегами привязки другой строкой - PullRequest
4 голосов
/ 31 декабря 2011

Мне нужно заменить строку между парой тегов привязки другой строкой. Чтобы быть более понятным:

<a blah blah>Click Here</a>

Я хочу заменить 'Click Here' на тег <img src=... />. Я перечитал пару других ресурсов, очень старался использовать инструмент регулярных выражений Ларса Олава Торвика, но потерпел неудачу!

Пожалуйста, помогите мне!

Ответы [ 4 ]

6 голосов
/ 01 января 2012

Не используйте 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, которая нарушит это решение, но необходимый для этого код будет настолько запутанным, что его практически не услышат.

4 голосов
/ 31 декабря 2011

Вы не должны использовать регулярные выражения для разбора HTML.HTML не является регулярным языком и поэтому не может быть правильно проанализирован с помощью регулярных выражений.Неважно, сколько вещей вы сложите в регулярное выражение, его можно обмануть.Рассмотрим, например, <a href=">Hello</a>">Hello</a>.

На каком бы языке вы ни работали, для этого почти наверняка есть библиотека для разбора HTML, которая делает это правильно.

Обязательный

2 голосов
/ 31 декабря 2011

Если вы знакомы с JQuery, это можно сделать довольно легко следующим образом:

Вот код HTML для примера сценария:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Untitled Document</title>

<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
$(function(){
    $("#testAnchor").html(" This is replaced image! <img src='http://www.google.com/logos/2011/newyearseve-2011-hp.jpg' />");


});
</script>
</head>

<body>

<a href="#"  id="testAnchor"> Click Here! </a>



</body>
</html>

Обратите внимание, что «Нажмите здесь!»заменяется на изображение и текст во время выполнения.Вы можете закомментировать следующую строку, чтобы увидеть страницу без замены «Нажмите здесь!»

// $("#testAnchor").html(" This is replaced image! <img src='http://www.google.com/logos/2011/newyearseve-2011-hp.jpg' />");
1 голос
/ 31 декабря 2011

Хорошо, если вы действительно хотите использовать регулярные выражения, вот шаблон <a[^>]*>(.*?)</a>
Код JavaScript.

var myrRegexp = /<a[^>]*>(.*?)<\/a>/i,
    subjectString = '<a blah blah>Click Here</a>',
    match = myrRegexp.exec(subjectString);
if (match != null && match.length > 1) {
    return match[1];
} else {
    return  = "";
}

C # код

string ResultString = "";
Regex RegexObj = new Regex("<a[^>]*>(.*?)</a>", RegexOptions.IgnoreCase);
ResultString = RegexObj.Match(SubjectString).Groups[1].Value;

PHP

if (preg_match('/<a[^>]*>(.*?)<\/a>/', '<a blah blah>Click Here</a>')) {

} else {

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...