使用 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):