使用 Html Agility Pack 将整个表单元素作为字符串获取
Get entire form element as string using Html Agility Pack
这是我第一次使用 Html Agility Pack 并立即遇到问题。
正如我的标题所暗示的那样,我希望将整个元素作为字符串获取,包括内部元素。
例如,下面是我的 html,我正在搜索 ID 为 aspnetForm
的表单元素
<html>
<head>
</head>
<body>
<form name="aspnetForm" id="aspnetForm">
<div id="div1">
<a href="div1-a1">Link 1 inside div1</a>
<a href="div1-a2">Link 2 inside div1</a>
</div>
<a href="a3">Link 3 outside all divs</a>
<div id="div2">
<a href="div2-a1">Link 1 inside div2</a>
<a href="div2-a2">Link 2 inside div2</a>
</div>
</form>
</body>
</html>
我希望输出以下内容(字符串)
<form name="aspnetForm" id="aspnetForm">
<div id="div1">
<a href="div1-a1">Link 1 inside div1</a>
<a href="div1-a2">Link 2 inside div1</a>
</div>
<a href="a3">Link 3 outside all divs</a>
<div id="div2">
<a href="div2-a1">Link 1 inside div2</a>
<a href="div2-a2">Link 2 inside div2</a>
</div>
</form>
我通常不喜欢问这样的spoon-feeding问题,但我一直在尝试和搜索,但找不到答案。
请帮忙!
提前致谢!
您似乎在寻找 HtmlNode.OuterHtml
:
//
// Summary:
// Gets or Sets the object and its content in HTML.
public virtual string OuterHtml { get; }
所以您只需要 select 您的表单节点并获取其 OuterHtml 属性:
HtmlDocument doc = ... // load your HTML
HtmlNode formNode = doc.DocumentNode.SelectSingleNode("//form[@id='aspnetForm']");
string entireElementAsString = formNode.OuterHtml;
更新
好像有个very old bug with how HAP treats form
tags. Or maybe it's a feature!
无论如何,这里有一个解决方法:
HtmlNode.ElementsFlags.Remove("form");
所以这应该有效:
HtmlNode.ElementsFlags.Remove("form");
HtmlDocument doc = ... // load your HTML
HtmlNode formNode = doc.DocumentNode.SelectSingleNode("//form[@id='aspnetForm']");
string entireElementAsString = formNode.OuterHtml;
确实是个好问题,奇怪的是以下所有问题都失败了!
使用 HtmlAgilityPack - 还不能想出解决方案!
(请注意,我也使用 nuget 库 ScraySharp,以获得 Css 选择器扩展(ScrapySharp.Extensions)
string html = @"<html>
<head>
</head>
<body>
<form name='aspnetForm' id='aspnetForm'>
<div id='div1'>
<a href='div1-a1'>Link 1 inside div1</a>
<a href='div1-a2'>Link 2 inside div1</a>
</div>
<a href='a3'>Link 3 outside all divs</a>
<div id='div2'>
<a href='div2-a1'>Link 1 inside div2</a>
<a href='div2-a2'>Link 2 inside div2</a>
</div>
</form>
</body>
</html>";
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
string result = string.Empty;
var formElement = doc.DocumentNode.CssSelect("form").FirstOrDefault();
var formChildren = formElement.Descendants();
StringBuilder sb = new StringBuilder();
if (formChildren != null)
{
foreach (var child in formChildren)
{
sb.AppendLine(child.InnerHtml);
}
}
//formElement.InnerHtml also returns empty !
Console.WriteLine(sb.ToString());
然而,您可以使用 AngleSharp 实现这一点 - 方法更简单(近来锐角似乎是值得推荐的选项,因为它仍然是 maintained/developed,而 HtmlAgility Pack 不是)。
使用 AngleSharp - 有效
HtmlParser parser = new HtmlParser();
var parsedDoc = parser.Parse(html);
Console.WriteLine(parsedDoc.QuerySelector("form").InnerHtml);
输出(使用 AngleSharp):
这是我第一次使用 Html Agility Pack 并立即遇到问题。
正如我的标题所暗示的那样,我希望将整个元素作为字符串获取,包括内部元素。
例如,下面是我的 html,我正在搜索 ID 为 aspnetForm
<html>
<head>
</head>
<body>
<form name="aspnetForm" id="aspnetForm">
<div id="div1">
<a href="div1-a1">Link 1 inside div1</a>
<a href="div1-a2">Link 2 inside div1</a>
</div>
<a href="a3">Link 3 outside all divs</a>
<div id="div2">
<a href="div2-a1">Link 1 inside div2</a>
<a href="div2-a2">Link 2 inside div2</a>
</div>
</form>
</body>
</html>
我希望输出以下内容(字符串)
<form name="aspnetForm" id="aspnetForm">
<div id="div1">
<a href="div1-a1">Link 1 inside div1</a>
<a href="div1-a2">Link 2 inside div1</a>
</div>
<a href="a3">Link 3 outside all divs</a>
<div id="div2">
<a href="div2-a1">Link 1 inside div2</a>
<a href="div2-a2">Link 2 inside div2</a>
</div>
</form>
我通常不喜欢问这样的spoon-feeding问题,但我一直在尝试和搜索,但找不到答案。
请帮忙!
提前致谢!
您似乎在寻找 HtmlNode.OuterHtml
:
//
// Summary:
// Gets or Sets the object and its content in HTML.
public virtual string OuterHtml { get; }
所以您只需要 select 您的表单节点并获取其 OuterHtml 属性:
HtmlDocument doc = ... // load your HTML
HtmlNode formNode = doc.DocumentNode.SelectSingleNode("//form[@id='aspnetForm']");
string entireElementAsString = formNode.OuterHtml;
更新
好像有个very old bug with how HAP treats form
tags. Or maybe it's a feature!
无论如何,这里有一个解决方法:
HtmlNode.ElementsFlags.Remove("form");
所以这应该有效:
HtmlNode.ElementsFlags.Remove("form");
HtmlDocument doc = ... // load your HTML
HtmlNode formNode = doc.DocumentNode.SelectSingleNode("//form[@id='aspnetForm']");
string entireElementAsString = formNode.OuterHtml;
确实是个好问题,奇怪的是以下所有问题都失败了!
使用 HtmlAgilityPack - 还不能想出解决方案!
(请注意,我也使用 nuget 库 ScraySharp,以获得 Css 选择器扩展(ScrapySharp.Extensions)
string html = @"<html>
<head>
</head>
<body>
<form name='aspnetForm' id='aspnetForm'>
<div id='div1'>
<a href='div1-a1'>Link 1 inside div1</a>
<a href='div1-a2'>Link 2 inside div1</a>
</div>
<a href='a3'>Link 3 outside all divs</a>
<div id='div2'>
<a href='div2-a1'>Link 1 inside div2</a>
<a href='div2-a2'>Link 2 inside div2</a>
</div>
</form>
</body>
</html>";
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
string result = string.Empty;
var formElement = doc.DocumentNode.CssSelect("form").FirstOrDefault();
var formChildren = formElement.Descendants();
StringBuilder sb = new StringBuilder();
if (formChildren != null)
{
foreach (var child in formChildren)
{
sb.AppendLine(child.InnerHtml);
}
}
//formElement.InnerHtml also returns empty !
Console.WriteLine(sb.ToString());
然而,您可以使用 AngleSharp 实现这一点 - 方法更简单(近来锐角似乎是值得推荐的选项,因为它仍然是 maintained/developed,而 HtmlAgility Pack 不是)。
使用 AngleSharp - 有效
HtmlParser parser = new HtmlParser();
var parsedDoc = parser.Parse(html);
Console.WriteLine(parsedDoc.QuerySelector("form").InnerHtml);
输出(使用 AngleSharp):