替换匹配的元素,包括嵌套元素

本文关键字:元素 嵌套 包括 替换 | 更新日期: 2023-09-27 18:12:42

我需要将span的所有出现替换为id="comment_n",其中n可以是任何数字,并且此合格span的任何出现都可以有嵌套的数字。每个span可以有不同的属性。例子:

foo <span id="comment_1">text <span id="comment_2" attr="value">text.</span></span> bar

我有这个正则表达式:

<span id="comment_'d+.+?<'/span>

但是它不包括最后一个结束的span标签。

我需要做一个替换:

Regex.Replace(input, regex, string.Empty, RegexOptions.Multiline | RegexOptions.IgnoreCase);

演示:http://regexr.com/3bpkf

替换匹配的元素,包括嵌套元素

我建议使用htmllagilitypack来获取所需的内容。可以指定XPath只获取具有以comment_开头的id属性的<span>标记(不区分大小写),然后删除它们。对comment_之后的数字的额外检查可以使用正则表达式完成,也可以不使用。这里有一种方法可以删除一些具有特定属性值的标签,其中该值是用正则表达式检查的。

public string HtmlAgilityPackRemoveTagsWithSpecificAttribute(string html, string xpath, string attribute_name, Regex rx)
{
    HtmlAgilityPack.HtmlDocument hap;
    Uri uriResult;
    if (Uri.TryCreate(html, UriKind.Absolute, out uriResult) &&
                              uriResult.Scheme == Uri.UriSchemeHttp)
    { // html is a URL 
        var doc = new HtmlAgilityPack.HtmlWeb();
        hap = doc.Load(uriResult.AbsoluteUri);
    }
    else
    { // html is a string
        hap = new HtmlAgilityPack.HtmlDocument();
        hap.LoadHtml(html);
    }
    var nodes = hap.DocumentNode.SelectNodes(xpath);
    if (nodes != null)
    {
       foreach (var node in nodes)
       {
           if (rx.IsMatch(node.Attributes[attribute_name].Value))
               node.ParentNode.RemoveChild(node);
       }
    }
    return hap.DocumentNode.OuterHtml;
}

你可以这样使用:

var res = HtmlAgilityPackRemoveTagsWithSpecificAttribute(html,
  "//span[starts-with(translate(@id, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
           'abcdefghijklmnopqrstuvwxyz'), 'comment_')]", "id", 
                new Regex("(?i)^comment_[0-9]+$"));

注意translate用于启用不区分大小写的比较(comment_, COMMENT_等)。如果你不需要,就使用starts-with(@id, 'comment_')]"

如果您多次使用regex,则可以在传递给方法之前将其实例化,或者使用静态Regex.IsMatch并替换方法签名。

至于为什么它不包括最后一个关闭span标签,这是因为您的regex模式中的?,这使得它"懒惰"导致它匹配最短的令人满意的字符串,如果您删除它,匹配将包括最后一个'span'标签:

<span id="comment_'d+.+<'/span>

但是我建议使用htmllagilitypack来解析你的DOM并操纵它

相关文章: