【问题标题】:How to delete a node if it has no parent node如果没有父节点,如何删除节点
【发布时间】:2012-04-17 12:35:27
【问题描述】:

我正在使用 HTML 敏捷包来清理所见即所得的输入。这可能不是最好的方法,但我正在与接触正则表达式的开发人员合作,所以它必须足够了。

我的所见即所得内容看起来像这样(例如):

<p></p>
<p></p>
<p><span><input id="textbox" type="text" /></span></p>

我需要去掉空的段落标签。这是我目前的做法:

HtmlNodeCollection nodes = doc.DocumentNode.SelectNodes("//p");
if (nodes == null)
    return;

foreach (HtmlNode node in nodes)
{
    node.InnerHtml = node.InnerHtml.Trim();
    if (node.InnerHtml == string.Empty)
        node.ParentNode.RemoveChild(node);
}

但是,由于 HTML 不是完整的文档,段落标签没有父节点,因此 RemoveChild 将失败,因为 ParentNode 为空。

我找不到其他删除标签的方法,谁能指出另一种方法?

【问题讨论】:

  • 将整个内容包装到一个div中,使用您当前的方法,然后删除父级? (可能使用更粗糙的东西,因为它更容易做)
  • 想指出像&lt;p&gt;&lt;p&gt;&lt;/p&gt;&lt;/p&gt; 这样的案例。清理这些东西有多重要?推进你的 foreach 将首先检查父级,发现它不为空,然后是子级,发现它为空并删除它,但现在父级为空但不会再次检查。
  • @Oded 不能分配给节点,因为它是一个 foreach 变量。
  • @VladCiobanu 我曾想过这个,但我想知道是否有更好的方法来解决这个问题。
  • @GuthMD 我不认为我们的 WYSIWYG 能够产生这种情况,但我不能肯定地排除它。这确实是一个好点,尽管我将在这之后过那座桥! =)

标签: c# asp.net .net html-agility-pack


【解决方案1】:

从技术上讲,第一级元素是文档根的子元素,所以下面的代码应该可以工作:

if (node.InnerHtml == String.Empty) {
    HtmlNode parent = node.ParentNode;
    if (parent == null) {
        parent = doc.DocumentNode;
    }
    parent.RemoveChild(node);
}

【讨论】:

  • 我试过(node.ParentNode ?? doc.DocumentNode).RemoveChild(node),但没有成功,所以我认为这样的事情是行不通的。这样做反而效果很好。
【解决方案2】:

你想从收藏中删除,对吧?

HtmlNodeCollection nodes = doc.DocumentNode.SelectNodes("//p");
if (nodes == null)
    return;

for (int i = 0; i < nodes.Count - 1; i++)
{
    nodes[i].InnerHtml = nodes[i].InnerHtml.Trim();
    if (nodes[i].InnerHtml == string.Empty)
        nodes.Remove(i);
}

【讨论】:

  • 我需要从文档中删除它,而不仅仅是集合。
  • 所以另一个答案更好,你还在使用foreach迭代吗?