2008-10-02 2 views
2

Мне нужно преобразовать встроенные атрибуты стиля CSS в их HTML-теги equivelants. Решение, которое у меня есть, но работает очень медленно, используя пространство имен Microsoft. Regex и длинные документы (~ 40 страниц html). Я пробовал несколько вариантов, но без каких-либо полезных результатов. Я сделал небольшую обертку вокруг выполнения выражений, но в итоге это всего лишь встроенный метод Regex Replace, который вызывается.ОЧЕНЬ медленное выполнение регулярного выражения при использовании больших документов

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

Я хочу, чтобы иметь возможность выполнить следующие модульные тесты:

[Test] 
public void TestCleanReplacesFontWeightWithB() 
{ 
    string html = "<font style=\"font-weight:bold\">Bold Text</font>"; 
    html = Q4.PrWorkflow.Helper.CleanFormatting(html); 
    Assert.AreEqual("<b>Bold Text</b>", html); 
} 
[Test] 
public void TestCleanReplacesMultipleAttributesFontWeightWithB() 
{ 
    string html = "<font style=\"font-weight:bold; color: blue; \">Bold Text</font>"; 
    html = Q4.PrWorkflow.Helper.CleanFormatting(html); 
    Assert.AreEqual("<b>Bold Text</b>", html); 
} 
[Test] 
public void TestCleanReplaceAttributesBoldAndUnderlineWithHtml() 
{ 
    string html = "<span style=\"font-weight:bold; color: blue; text-decoration: underline; \">Bold Text</span>"; 
    html = Q4.PrWorkflow.Helper.CleanFormatting(html); 
    Assert.AreEqual("<u><b>Bold Text</b></u>", html); 
} 
[Test] 
public void TestCleanReplaceAttributesBoldUnderlineAndItalicWithHtml() 
{ 
    string html = "<span style=\"font-weight:bold; color: blue; font-style: italic; text-decoration: underline; \">Bold Text</span>"; 
    html = Q4.PrWorkflow.Helper.CleanFormatting(html); 
    Assert.AreEqual("<u><b><i>Bold Text</i></b></u>", html); 
} 
[Test] 
public void TestCleanReplacesFontWeightWithSpaceWithB() 
{ 
    string html = "<font size=\"10\" style=\"font-weight: bold\">Bold Text</font>"; 
    html = Q4.PrWorkflow.Helper.CleanFormatting(html); 
    Assert.AreEqual("<b>Bold Text</b>", html); 
} 

Регулярное expresion я использую для достижения этой логики работает, но очень медленно. Регулярное выражение в C# код выглядит следующим образом:

public static IReplacePattern IncludeInlineItalicToITag(ICleanUpHtmlFactory factory) 
{ 
    return factory.CreateReplacePattern("(<(span|font) .*?style=\".*?font-style:\\s*italic[^>]*>)(.*?)</\\2>", "$1<i>$3</i></$2>"); 
} 
public static IReplacePattern IncludeInlineBoldToBTag(ICleanUpHtmlFactory factory) 
{ 
    return factory.CreateReplacePattern("(<(span|font) .*?style=\".*?font-weight:\\s*bold[^>]*>)(.*?)</\\2>", "$1<b>$3</b></$2>"); 
} 
public static IReplacePattern IncludeInlineUnderlineToUTag(ICleanUpHtmlFactory factory) 
{ 
    return factory.CreateReplacePattern("(<(span|font) .*?style=\".*?text-decoration:\\s*underline[^>]*>)(.*?)</\\2>", "$1<u>$3</u></$2>"); 
} 
+0

Прежде чем ответить на вопрос, какую версию платформы .NET вы используете? Если вы в настоящее время не используете .NET 3.5, стоит ли это обновить, чтобы получить? –

ответ

7

Я считаю, что проблема в том, что, если он находит пролет | шрифт тег, который не имеет атрибута стиля определен, он будет продолжать искать его до конца документа из-за ". *?". Я не тестировал его, но менял его на «[^>] *?» может улучшить производительность.

EDIT: Убедитесь, что вы применили это изменение для всех «. *?». у тебя есть; даже тот, который захватывает содержимое между тегами (используйте «[^ <] *?» там), потому что, если файл не правильно сформирован, он будет захватывать до следующего закрывающего тега.

+0

Согласовано. Каждый раз, когда вы пытаетесь улучшить регулярное выражение (будь то производительность, ясность или многое другое),. * - это первое, на что вы должны обратить внимание и попытаться устранить. –

+0

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

0

.NET регулярные выражения не поддерживают рекурсивные конструкции. PCRE делает, но это не имеет значения здесь.

рассмотривать

<font style="font-weight: bold;"> text1 <font color="blue"> text2 </font> text3 </font> 

Было бы получить преобразованы в

<b> text1 <font color="blue"> text2 </b> text3 </font> 

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

Редактировать: Scratch that. Кажется, .NET имеет конструкцию для сбалансированных, рекурсивных шаблонов. Но не так сильно, как в PCRE/perl.

(?<N>content) would push N onto a stack if content matches 
(?<-N>content) would pop N from the stack, if content matches. 
(?(N)yes|no) would match "yes" if N is on the stack, otherwise "no". 

Для получения более подробной информации см. http://weblogs.asp.net/whaggard/archive/2005/02/20/377025.aspx.

+0

Вполне возможно справиться с этим в NET. См. Балансировочные группы в регулярных выражениях, это позволяет вам, например, сопоставлять скользящие круглые скобки. http://oreilly.com/catalog/regex2/chapter/index.html –

0

Дикая догадка: я считаю, что стоимость исходит от альтернативы и соответствующего соответствия. Вы можете попробовать заменить:

"(<(span|font) .*?style=\".*?font-style:\\s*italic[^>]*>)(.*?)</\\2>", "$1<i>$3</i></$2>" 

с двумя отдельными выражениями:

"(<span .*?style=\".*?font-style:\\s*italic[^>]*>)(.*?)</span>", "$1<i>$2</i></span>" 
"(<font .*?style=\".*?font-style:\\s*italic[^>]*>)(.*?)</font>", "$1<i>$2</i></font>" 

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

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

0

Во время тестирования я обнаружил странное поведение. При запуске регулярного выражения в отдельном потоке он выполняется намного быстрее. У меня есть скрипт sql, который я разделял на разделы с Go to Go, используя regexp. При работе над этим скриптом, не использующим отдельный поток, он длится около 2 минут. Но при использовании многопоточности он занимает всего несколько секунд.

Смежные вопросы