如何修改所有匹配的标题:
<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]", "")
但我如何将两者合并?
答案 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="…"
,其中…
是元素的内部文本删除了所有非单词字符(通过应用内部正则表达式)。
修改:添加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,那可能会非常可怕。