我需要将内联css样式属性转换为其HTML标记等价物。我拥有的解决方案有效,但是使用Microsoft .Net 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);
}
我用于实现此逻辑的常规表达式是有效的,但是非常慢。 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>");
}
我相信问题是,如果找到span
| font
标记,但未定义样式属性,由于.\*?
,它将继续寻找直到文档结尾。我尚未对其进行测试,但是将其更改为[^>]\*?
可能会提高性能。
确保您对所有.\*?
应用该更改;即使是捕获标签之间内容的标签(在那里使用[^<]\*?
),因为如果文件格式不正确,它将捕获多达下一个结束标签。
。NET正则表达式不支持递归构造。 PCRE可以,但是在这里无关紧要。
Concider
<font style="font-weight: bold;"> text1 <font color="blue"> text2 </font> text3 </font>
它将转换为
<b> text1 <font color="blue"> text2 </b> text3 </font>
我的建议是使用适当的标记解析器,并可能在样式标签的值上使用regexp。
编辑:抓取。 .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。
疯狂猜测:我相信费用来自替代方案和相应的匹配项。您可能要尝试替换:
"(<(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的不是人为的错误或小小的事情,而是具有明确定义的模式的过程。
在测试期间,我发现了奇怪的行为。当在单独的线程中运行regexp时,它的运行速度要快得多。我有使用regexp从Go转到Go拆分为sql脚本的部分。在不使用单独线程的情况下使用此脚本时,该脚本持续约2分钟。但是,当使用多线程时,它仅持续数秒。