Регулярное выражение замены тега HTML не совсем правильно работает

Это продолжение моего другого вопроса . Решение, которое я нашел, отлично работало для каждого из тестов, которые я ему задавал, пока не обнаружился случай, который ускользнул от меня в первый раз.

Моя цель - переформатировать неправильно отформатированные атрибуты тегов с помощью регулярных выражений (я знаю, что, возможно, это не надежный метод, как я узнаю, но терпите меня).

Мои функции:

Public Function ConvertMarkupAttributeQuoteType(ByVal html As String) As String
    Dim findTags As String = "</?\w+((\s+\w+(\s*=\s*(?:"".*?""|'.*?'|[^'"">\s]+))?)+\s*|\s*)/?>"
    Return Regex.Replace(html, findTags, AddressOf EvaluateTag)
End Function

Private Function EvaluateTag(ByVal match As Match) As String
    Dim attributes As String = "\s*=\s*(?:(['""])(?<g1>(?:(?!\1).)*)\1|(?<g1>\S+))"
    Return Regex.Replace(match.Value, attributes, "='$2'")
End Function

Регулярное выражение в функции EvaluateTag будет правильно преобразовывать HTML, например

<table border=2 cellpadding='2' cellspacing="1">

в

<table border='2' cellpadding='2' cellspacing='1'>

Вы заметите, что я заставляю значения атрибутов заключать в одинарные кавычки — не беспокойтесь об этом. Случай, в котором он прерывается, заключается в том, что значение атрибута last не имеет ничего вокруг себя.

<table width=100 border=0>

выходит из регулярного выражения заменить как

<table width='100' border='0>'

с последней одинарной кавычкой неправильно вне тега. Я уже признавался, что совсем не разбираюсь в регулярных выражениях; Я просто не нашел времени, чтобы понять все, что он может сделать. Итак, я прошу помощи в настройке регулярного выражения EvaluateTag, чтобы оно могло обрабатывать этот последний случай.

Спасибо!


person Cᴏʀʏ    schedule 14.09.2009    source источник
comment
Я думаю, вам будет намного лучше использовать инструмент очистки HTML (как предложил da8 по вашему другому вопросу) или проанализировать HTML с помощью прощающего DOM и повторно экспортировать его.   -  person TrueWill    schedule 14.09.2009


Ответы (2)


Первая функция RegEx передаст EvaluateTag полное совпадение, то есть весь HTML-тег.

Но EvaluateTag не игнорирует последний символ больше...

Боюсь, мне еще не хватило кофеина, чтобы проработать все выражение, но эта корректировка может работать (добавлено больше, чем в список символов):

 Private Function EvaluateTag(ByVal match As Match) As String
   Dim attributes As String = "\s*=\s*(?:(['"">])(?<g1>(?:(?!\1).)*)\1|(?<g1>\S+))"
   Return Regex.Replace(match.Value, attributes, "='$2'")
 End Function
person richardtallent    schedule 14.09.2009
comment
Это не совсем сработало. На самом деле, это никак не повлияло на исходное регулярное выражение. - person Cᴏʀʏ; 15.09.2009

Объяснение Ричардталлента о том, почему регулярное выражение не работает, указало мне правильное направление. Немного поигравшись, следующая замена функции EvaluateTag, кажется, работает.

Может ли кто-нибудь увидеть что-нибудь проблемное с этим? Сделанное мной изменение находится в последней группе после трубы. Может быть, это может быть еще более упрощено дальше?

 Private Function EvaluateTag(ByVal match As Match) As String
   Dim attributes As String = "\s*=\s*(?:(['""])(?<g1>(?:(?!\1).)*)\1|(?<g1>[^>\s]+))"
   Return Regex.Replace(match.Value, attributes, "='$2'")
 End Function

Если никто не ответит, я, вероятно, приму это как ответ. Спасибо еще раз!

person Cᴏʀʏ    schedule 15.09.2009