HtmlAgilityPack 替换节点

31

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

我尝试了以下方法,但我无法弄清楚如何获取节点的索引或调用哪个父节点的 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( )
}
2个回答

66

要创建一个新的节点,请使用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 <b>node</b> <strong>another node</strong>',则替换无法正常工作。 - Omar
如果该项具有多个标签,例如<em><strong>test</strong></em>,则此方法无效。 - Jason Dias
@Jason:当然可以……你真的_尝试_了吗? - Jeff Mercado
@JeffMercado 是的,但我认为只是我的代码有问题。听起来很疯狂,但在调试时我得到了不同的结果。无论如何,感谢你的快速回复。 - Jason Dias
请注意,我们需要在查询上调用 ToList() 方法,因为我们将修改文档,如果不这样做,查询将失败。该语句对我非常有用。谢谢。 - Ahmed Mostafa
显示剩余8条评论

-1
已经实现了以下解决方案以达到相同的效果。
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 对象,然后将其附加为相应对象的子级。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接