Is there a better way to remove span elements but leave child nodes?

Viewed 666

I want to remove all span elements (without attributes) but leave the inner html. I have created the following code snippet which appears to work but I can't help thinking this is overly complicated for such a task. Is there a better way?

var config = Configuration.Default.WithDefaultLoader().WithCss();
var parser = new HtmlParser(config);
var document = parser.Parse("<p><span><span><em>span text</em></span> </span> span text</p>");

foreach (var element in document.Descendents())
{
    var parent = element.Parent;
    while (parent != null)
    {
        var span = parent as IHtmlSpanElement;
        if (span != null && !span.Attributes.Any())
        {
            span.Replace(span.ChildNodes.ToArray());
        }
        parent = parent.Parent;
    }
}

document.Body.InnerHtml.Dump();

// outputs: <p><em>span text</em>  span text</p>
1 Answers

What you want is a replacement. Luckily, such an API exists, which you already use (Replace). However, most of your boilerplate code can also be replaced with standard APIs (like QuerySelectorAll):

var config = Configuration.Default.WithDefaultLoader().WithCss();
var parser = new HtmlParser(config);
var document = parser.Parse("<p><span><span><em>span text</em></span> </span> span text</p>");

foreach (var element in document.QuerySelectorAll("span").Where(m => m.Attributes.Length == 0))
{
    element.Replace(element.ChildNodes.ToArray());
}

document.Body.InnerHtml.Dump();

Note: I've only placed the Where to have the same condition as you placed in your code - namely no attribute should be found on these span elements.

Hope this helps!

Related