使用HTML Agility Pack移除嵌套strong和em标签的实现问题
Got it, let's fix that nested emphasis tag problem you're facing. The issue with your current code is that it only handles single-level nesting—we need a recursive approach to strip all inner <b>, <strong>, <i>, and <em> tags while preserving the outermost one, no matter how deep the nesting goes.
Step-by-Step Explanation
The core idea is:
- Identify all "outermost" emphasis tags (those not wrapped inside another bold/italic tag).
- Recursively traverse each outermost tag's descendants, removing any nested emphasis tags and merging their content into the parent.
Working Code
Here's a complete implementation using HTML Agility Pack:
using HtmlAgilityPack; using System.Collections.Generic; using System.Linq; public static class HtmlCleaner { private static readonly HashSet<string> _emphasisTags = new HashSet<string> { "b", "strong", "i", "em" }; public static string StripNestedEmphasisTags(string html) { var doc = new HtmlDocument(); doc.LoadHtml(html); // Find all outermost emphasis tags (not inside another emphasis tag) var outerEmphasisNodes = doc.DocumentNode.Descendants() .Where(n => _emphasisTags.Contains(n.Name.ToLower()) && !_emphasisTags.Contains(n.ParentNode.Name.ToLower())) .ToList(); // Process each outermost tag to remove nested emphasis tags foreach (var node in outerEmphasisNodes) { RemoveNestedEmphasisRecursively(node); } return doc.DocumentNode.OuterHtml; } private static void RemoveNestedEmphasisRecursively(HtmlNode parentNode) { // Iterate backwards to avoid index issues when removing nodes for (int i = parentNode.ChildNodes.Count - 1; i >= 0; i--) { var childNode = parentNode.ChildNodes[i]; if (_emphasisTags.Contains(childNode.Name.ToLower())) { // Move all child content of the nested tag up to the parent parentNode.InsertBefore(childNode.ChildNodes, childNode); // Delete the nested emphasis tag itself childNode.Remove(); } else { // Recurse into non-emphasis child nodes to check for deeper nesting RemoveNestedEmphasisRecursively(childNode); } } } }
How to Use It
Call the static method with your input HTML:
string inputHtml = "<b>Hello <strong>world <i>foo</i></strong></b>"; string cleanedHtml = HtmlCleaner.StripNestedEmphasisTags(inputHtml); // Output: <b>Hello world foo</b>
Test Cases & Results
- Single-level nesting:
<i>Hi <em>there</em></i>→<i>Hi there</i> - Multi-level mixed nesting:
<b>abc <i>def <strong>ghi</strong></i></b>→<b>abc def ghi</b> - Multiple outer tags:
<div>Test <b>xxx</b> <i>yyy <b>zzz</b></i> end</div>→<div>Test <b>xxx</b> <i>yyy zzz</i> end</div>
Key Details
- Backwards iteration: We loop from the last child to the first to avoid index shifting issues when removing nodes.
- Recursive traversal: Ensures even deeply nested tags (like 3+ levels down) are stripped properly.
- Outermost tag check: We only process tags that aren't wrapped inside other emphasis tags, so we don't accidentally strip the tag we want to keep.
内容的提问来源于stack exchange,提问作者trfletch
相关产品推荐
相关产品推荐

