找到标题然后修改它们

时间:2012-02-28 19:45:14

标签: c# regex

如何修改所有匹配的标题:

<h1>Some heading!</h1>

<h1 id="Someheading">Some heading!</h1>

匹配的正则表达式是

var regex = new Regex(@"<[hH]([1-3])>(.+?)</[hH][1-3]>");

并通过

进行修剪
Regex.Replace(heading.Title, @"[\W]", "")

但我如何将两者合并?

2 个答案:

答案 0 :(得分:3)

我知道这看起来不漂亮,但它确实有效。您应该通过将一些嵌套转换提取到单独的方法中来重构它。

var regex = new Regex(@"<(h[1-3])>(?<val>.+?)</\1>",
    RegexOptions.IgnoreCase | RegexOptions.Singleline);  
string html = "<h1>Some heading!</h1>";

var result = regex.Replace(html, match => 
    match.Value.Insert(3, string.Format(" id=\"{0}\"", 
        Regex.Replace(match.Groups["val"].Value, @"\W+", ""))));

我修复了原来的正则表达式:

  • 它变得不区分大小写
  • 它定义了一个命名子表达式val,用于匹配元素的内部文本
  • 结束标记必须通过反向引用\1与开始标记匹配,从而阻止匹配,例如<h1>Hello</h2>

然后,我将正则表达式应用于HTML文档(可能包含任意数量的h1 - h3元素)。对于每个匹配,我在开始标记中插入一个新字符串(在<h1之后),这相当于id="…",其中是元素的内部文本删除了所有非单词字符(通过应用内部正则表达式)。

根据w0lf的观察结果,

修改:添加RegexOptions.Singleline以匹配跨越多行的标题。

答案 1 :(得分:2)

如果你必须这样做,那么我真的认为HtmlAgilityPack 过度杀伤。

这只是一个~130K dll而且它允许你这样做:

const string someHtml = "<h1>Some heading!</h1>\r\n" +
                        "<h2>Some sub-heading!</h2>\r\n" +
                        "<p> Some text in here</p>\r\n" +
                        "<h3> Another heading, this time\r\n" +
                        "spanning two rows</3>\r\n";

var htmlDocument = new HtmlDocument();

htmlDocument.LoadHtml(someHtml);

htmlDocument.DocumentNode.SelectNodes("//h1")
.Union(htmlDocument.DocumentNode.SelectNodes("//h2"))
.Union(htmlDocument.DocumentNode.SelectNodes("//h3"))
.ToList()
.ForEach(node => node.Attributes.Add("id", 
    new string(node.InnerText.ToCharArray()
                  .Where(char.IsLetterOrDigit).ToArray())));

Console.WriteLine(htmlDocument.DocumentNode.OuterHtml);

上面的代码产生:

<h1 id="Someheading">Some <a href="http://somelink">heading</a>!</h1>
<h2 id="Somesubheading">Some sub-heading!</h2>
<p> Some text in here</p>
<h3 id="Anotherheadingthistimespanningtworows"> Another heading, this time
spanning two rows</h3>

我认为这段代码相对容易生成和理解,它处理的情况如下:

  • 嵌套代码
  • 跨越多行的标签
  • 空标记

如果不是无法处理Regex,那可能会非常可怕。