Создайте регулярное выражение, чтобы найти и заменить недопустимые атрибуты HTML - PullRequest
1 голос
/ 31 июля 2009

Печальная правда об этом посте в том, что у меня плохие навыки регулярных выражений. Недавно я наткнулся на некоторый код в старом проекте, с которым я действительно хочу что-то сделать. Вот оно:

strDocument = strDocument.Replace("font size=""1""", "font size=0.2")
strDocument = strDocument.Replace("font size='1'", "font size=0.2")
strDocument = strDocument.Replace("font size=1", "font size=0.2")
strDocument = strDocument.Replace("font size=""2""", "font size=1.5")
strDocument = strDocument.Replace("font size='2'", "font size=1.5")
strDocument = strDocument.Replace("font size=2", "font size=1.5")
strDocument = strDocument.Replace("font size=3", "font size=2")
strDocument = strDocument.Replace("font size=""3""", "font size=2")
strDocument = strDocument.Replace("font size='3'", "font size=2")

Я предполагаю, что есть некоторый простой шаблон регулярных выражений, который я мог бы использовать, чтобы найти различные способы цитирования значений атрибутов и заменить их допустимым синтаксисом. Например, если кто-то написал какой-нибудь HTML-код, похожий на:

<tag attribute1=value attribute2='value' />

Я хотел бы иметь возможность легко очистить этот тег, чтобы он выглядел как

<tag attribute1="value" attribute2="value" />

Веб-приложению, с которым я работаю, 10 лет, и существует несколько тысяч ошибок проверки из-за пропущенных кавычек и тонны другого мусора, так что если кто-нибудь сможет мне помочь, это будет здорово!

EDIT:

Я обернулся (нашел несколько примеров), и у меня есть кое-что, что будет работать, но хотелось бы, чтобы оно было немного умнее:

Dim input As String = "<tag attribute=value attribute='value' attribute=""value"" />"
Dim test As String = "attribute=(?:(['""])(?<attribute>(?:(?!\1).)*)\1|(?<attribute>\S+))"
Dim result As String = Regex.Replace(input, test, "attribute=""$2""")

Это выводит result правильно как:

<tag attribute="value" attribute="value" attribute="value" />

Есть ли способ, которым я мог бы немного изменить (и упростить!) Это, чтобы заставить его искать любое имя атрибута?

UPDATE:

Вот то, что я пока основал на комментариях. Возможно, это можно улучшить еще больше:

Dim input As String = "<tag border=2 style='display: none' width=""100%"" />"
Dim test As String = "\s*=\s*(?:(['""])(?<g1>(?:(?!\1).)*)\1|(?<g1>\S+))"
Dim result As String = Regex.Replace(input, test, "=""$2""")

, который производит:

<tag border="2" style="display: none" width="100%" />

Есть еще предложения? В противном случае, я думаю, я ответил на свой вопрос, конечно, с вашей помощью.

Ответы [ 5 ]

3 голосов
/ 02 августа 2009

А как насчет использования такого инструмента, как Tidy (http://tidy.sourceforge.net/)), который может очистить ваш HTML-код, вместо этого самостоятельно выискивая ошибку проверки с помощью regex? Просто мои два цента.

1 голос
/ 31 июля 2009

Я думаю, что лучше не смешивать это в одном мега-регулярном выражении. Я бы предпочел несколько шагов:

  1. Идентификационный тег: <([^>]+)/?>
  2. Заменить неправильные атрибуты правильными итеративно через строку тега: заменить шаблон \s+([\w]+)\s*=\s*(['"]?)(\S+)(\2) на $1="$3" (с пробелом после последней цитаты). Я думаю, что .net позволяет отслеживать границы совпадения. Это может помочь избежать поиска по уже исправленной части тега.
0 голосов
/ 16 сентября 2010

У меня были проблемы с тем, что окончательное обновление (21.08.09) заменит

<font color=red size=4>

с

<font color="red" size="4>"

(размещение закрывающей кавычки на втором атрибуте вне закрывающего тега)

Я изменил строку атрибутов в EvaluateTag на:

Dim attributes As String = "\s*=\s*(?:('|"")(?<g1>(?:(?!\1).)*)\1|(?<g1>[^>|\s]+))"

изменено [^>|\s] на ближнем конце.

Это возвращает мои желаемые результаты: <font color="red" size="4">

Это работает на моем исчерпывающем тестовом примере.

0 голосов
/ 22 августа 2009

Вот конечный продукт. Надеюсь, это кому-нибудь поможет!

Imports System.Text.RegularExpressions

Module Module1

    Sub Main()
        Dim input As String = "<tag border=2 style='display: none' width=""100%"">Some stuff""""""in between tags==="""" that could be there</tag>" & _
            "<sometag border=2 width=""100%"" /><another that=""is"" completely=""normal"">with some content, of course</another>"

        Console.WriteLine(ConvertMarkupAttributeQuoteType(input, "'"))
        Console.ReadKey()
    End Sub

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

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

End Module

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

0 голосов
/ 31 июля 2009

отбросьте слово «атрибут», т.е.

Dim test As String = "=(?:(['""])(?<attribute>(?:(?!\1).)*)\1|(?<attribute>\S+))" 

, который будет находить каждую строку "= 'что-то'", хорошо, если у вас нет другого кода на страницах, т.е.

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