Simple & Funny——用正则表达式处理html文档

来源:互联网 发布:java 优秀代码 编辑:程序博客网 时间:2024/05/29 03:05

有一份html文件,里面有很多的网址引用的是相对地址,比如说,需要把它改成绝对地址,例如www.codeproject.com/image/logo.gif />。由于源文件体积不小,因此需要一个快速而且资源占用不大的处理方法。

?

我当时的第一反应就是使用正则表达式,因为与其它方式,比如说直接处理字符串或者使用XmlReader/XmlWriter等相比,正则表达式的速度和资源占用都是最佳的。因此,仔细考虑之后,我写成了下面的代码:

?

using System;using System.Text.RegularExpressions;using System.IO;class EvalDemo{    public static string GetResult(Match m)    {        return Regex.Replace(m.Value, @"[/]", @"http://www.codeproject.com/");    }}class Demo{    public static void Main()    {        StreamReader reader=File.OpenText("source.txt");        string source=reader.ReadToEnd();        reader.Close();        string reg=@"href/s*=/s*[""']?/";        string result=Regex.Replace(source, reg, new MatchEvaluator(EvalDemo.GetResult));        Console.WriteLine(result);    }}

?

其中,放置在同一目录下的source.txt文件保存有需要修改的html源文件,当然你也可以把它放在其它目录下,或者采用不同的方式来获得,例如通过HttpResponse来获取相含有该文件的流。

?

在打开该文件并读入内存后,我使用StreamReader.ReadToEnd方法获取了流内容的字符串表示,然后用正则表达式对这一字符串进行操作。也许你会问,直接通过查找把所有的href=”/替换成href=”www.codeproject.com/不可以吗?这样是可以的,但如果html代码变成了href=/那么就无法处理了,另外因为html允许在有效字符间留有空格,所以如果用户在html文件中把代码写成href =? /,那么你也必须把这种情况考虑在内(尽管不太会发生),这样你的string.Replace方法就会变得很复杂,而应用正式表达式来处理这一问题就会简单多了,请看下面这行代码:

?

string reg=@"href/s*=/s*[""']?/";

?

如果你此前没接触过正则表达式,那么可能会感到有些复杂。其实只要我把其中各项所代表的内容解释在下面,你就会发现其实正则表达式没什么神秘的:

?

字符

含义

/s

匹配一个空白字符,比如全角空格、半角空格、制表符等

*

表示它前面的项目(/s)可以有零个或多个匹配,也就是说这里既可以没有空格,也可以有多个空格

[]

匹配其中的单个字符

[“”’]

匹配这两个字符:双引号或者单引号。由于双引号在C#里有特殊含义,因此需要以两个双引号的形式来表示单个双引号

表示它前面的项目([“”’])可以有一个或多个匹配,与*的用法相似

?

有了上面的解释,再去看那段正则表达式是不是很简单了?其实就是要找一段类似href=”/的字符串,其中可能会含有一些空白字符或可选字符。好了,接着往下看。

?

string result=Regex.Replace(source, reg, new MatchEvaluator(EvalDemo.GetResult));

?

这是标准的正则表达式替换操作的用法,其中前两项参数的用意非常明确,而第三项参数比较特殊:在这里创建了一个MatchEvaluator委托的实例,并传入了一个回调方法——EvalDemo.GetResult的地址。为什么要这样设计呢?其实一般的正则表达式替换操作是不需要这样复杂的,你只需指定要替换的源,要替换的字符,以及替换后的字符即可,但在这个示例里情况很特殊——你无法确切获知要被替换的是什么字符!不是吗?可能是href=”/,也可能是href=’/,甚至可能是href?? =??? /,因此你需要通过一个回调函数来处理这个变化多端的字符串,在处理后传回处理结果,例如对于href=”/而言,处理结果将是href=”/www.codeproject.com,而href=’/的处理结果则是href=’/www.codeproject。理解了这一点以后,就请来看看这个简单有趣的回调方法:

?

class EvalDemo
{
??? public static string GetResult(Match m)
??? {
??????? return Regex.Replace(m.Value, @"[/]", @"http://www.codeproject.com/");
??? }
}

?

在这里,回调方法其实是自定义的EvalDemo类的静态方法,该方法接受一个Match类实例,通过Match.Value可以获得需要处理的字符串,然后对该字符串加以处理即可。因此,在GetResult方法里,我用了一个最基本的正则表达式替换操作,查找所有需要处理的字符串中的/(斜杠)字符,把它替换成http://www.codeproject.com,然后返回结果。这样,Main中的替换操作便获得了所需的第三个参数,替换操作可以进行了。

?

最后,为了演示方便,我把最终结果(即修改后的html文件内容)打印到Console上面。你可以自己选择是否打印,或者保存到文件中。

?

OK,一个不太复杂的正则表达式的应用就讲解到这里了,希望能通过这篇文章带你进入正则表达式的大门。如果你对本文有任何意见或看法,欢迎提出来!笑脸