【问题标题】:HtmlAgilityPack replace nodeHtmlAgilityPack 替换节点
【发布时间】:2019-08-05 16:27:11
【问题描述】:

我想用一个新节点替换一个节点。如何获取节点的确切位置并进行完全替换?

我尝试了以下方法,但我不知道如何获取节点的索引或在哪个父节点上调用ReplaceChild()

string html = "<b>bold_one</b><strong>strong</strong><b>bold_two</b>";
HtmlDocument document = new HtmlDocument();
document.LoadHtml(html);

var bolds = document.DocumentNode.Descendants().Where(item => item.Name == "b");

foreach (var item in bolds)
{

    string newNodeHtml = GenerateNewNodeHtml();
    HtmlNode newNode = new HtmlNode(HtmlNodeType.Text, document, ?);
    item.ParentNode.ReplaceChild( )
}

【问题讨论】:

    标签: c# html-agility-pack


    【解决方案1】:

    新建节点,使用HtmlNode.CreateNode()工厂方法,不要直接使用构造函数。

    这段代码应该适合你:

    var htmlStr = "<b>bold_one</b><strong>strong</strong><b>bold_two</b>";
    var doc = new HtmlDocument();
    doc.LoadHtml(htmlStr);
    
    var query = doc.DocumentNode.Descendants("b");
    foreach (var item in query.ToList())
    {
        var newNodeStr = "<foo>bar</foo>";
        var newNode = HtmlNode.CreateNode(newNodeStr);
        item.ParentNode.ReplaceChild(newNode, item);
    }
    

    请注意,我们需要在查询中调用ToList(),我们将修改文档,如果不这样做,它将失败。


    如果你想用这个字符串替换:

    "some text <b>node</b> <strong>another node</strong>"
    

    问题在于它不再是单个节点而是一系列节点。您可以使用HtmlNode.CreateNode() 很好地解析它,但最后,您只引用了序列的第一个节点。您需要使用父节点进行替换。

    var htmlStr = "<b>bold_one</b><strong>strong</strong><b>bold_two</b>";
    var doc = new HtmlDocument();
    doc.LoadHtml(htmlStr);
    
    var query = doc.DocumentNode.Descendants("b");
    foreach (var item in query.ToList())
    {
        var newNodesStr = "some text <b>node</b> <strong>another node</strong>";
        var newHeadNode = HtmlNode.CreateNode(newNodesStr);
        item.ParentNode.ReplaceChild(newHeadNode.ParentNode, item);
    }
    

    【讨论】:

    • 有没有办法用多个其他节点替换一个节点?例如,如果newNodeStr='some text &lt;b&gt;node&lt;/b&gt; &lt;strong&gt;another node&lt;/strong&gt;',则替换不起作用。
    • @Omar:已更新。如果您使用HtmlNode.CreateNode() 解析该字符串,它将导致创建对第一个节点的引用。所以如果你用那个替换,你只会看到第一个被替换。您实际上应该替换 ParentNode 以获取所有这些。
    • 经过考虑,始终使用ParentNode 可能是安全的,因为在进行替换时,新的单节点的父节点实际上就是它自己。
    • 如果项目有多个标签,例如,这将不起作用。 测试
    • @Jason:当然可以……你真的尝试过吗?
    【解决方案2】:

    已实施以下解决方案以实现相同目的。

    var htmlStr = "<b>bold_one</b><div class='LatestLayout'><div class='olddiv'><strong>strong</strong></div></div><b>bold_two</b>";
    var htmlDoc = new HtmlDocument();
        HtmlDocument document = new HtmlDocument();
        document.Load(htmlStr);
    
    htmlDoc.DocumentNode.SelectSingleNode("//div[@class='olddiv']").Remove();
    htmlDoc.DocumentNode.SelectSingleNode("//div[@class='LatestLayout']").PrependChild(newChild)
    
    htmlDoc.Save(FilePath); // FilePath .html file with full path if need to save file.
    

    所以选择一个对象并删除相应的 HTML 对象

    并将其附加为智利。各自的对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多