2014-04-23 41 views
5

我写简单的屏幕在C#刮方案,为此,我需要选择所有输入的放在一个名为“aspnetForm”单一形式的内部不工作(有在页面上2种形式,而且我不想从另一个输入中获得输入),并且此表单中的所有输入都放置在不同的表格,div中,或者仅在此表单的第一个子级别中。在HTMLAgilityPack的XPath选择的预期

所以我写的非常简单的XPath查询:

//form[@id='aspnetForm']//input 

它的作品如预期在我测试器(Chrome,IE,Firefox)的所有浏览器 - 它返回我想要什么。

但是在HTMLAgilityPack中它根本不起作用 - SelectNodes总是返回NULL。

我为测试编写此查询工作正常,但返回不是我想要的。首先选择所有输入的是第一孩子的我的形式,而第二只回归的形式:

//form[@id='aspnetForm']/input 
//form[@id='aspnetForm'] 

是的,我知道我可以只从上次查询枚举节点,或作出它的结果是另一个的SelectNodes,但我真的不想这样做。我想使用与浏览器中相同的查询。

目前XPath中断了HTMLAgilityPack?有什么替代XPath实现C#?

using HtmlAgilityPack; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 

namespace HtmlAGPTests 
{ 
    [TestClass] 
    public class XPathTests 
    { 
     private const string html = 
       "<form id=\"aspnetForm\">" + 
       "<input name=\"first\" value=\"first\" />" + 
       "<div>" + 
        "<input name=\"second\" value=\"second\" />" + 
       "</div>" + 
       "</form>"; 

     private static HtmlNode GetHtmlDocumentNode() 
     { 
      var document = new HtmlDocument(); 
      document.LoadHtml(html); 
      return document.DocumentNode; 
     } 

     [TestMethod] 
     public void TwoLevelXpathTest()  // fail - nodes is NULL actually. 
     { 
      var query = "//form[@id='aspnetForm']//input"; // what i want 
      var documentNode = GetHtmlDocumentNode(); 

      var inputNodes = documentNode.SelectNodes(query); 

      Assert.IsTrue(inputNodes.Count == 2); 
     } 

     [TestMethod] 
     public void TwoSingleLevelXpathsTest()  // works 
     { 
      var formQuery = "//form[@id='aspnetForm']"; 
      var inputQuery = "//input"; 
      var documentNode = GetHtmlDocumentNode(); 

      var formNode = documentNode.SelectSingleNode(formQuery); 
      var inputNodes = formNode.SelectNodes(inputQuery); 

      Assert.IsTrue(inputNodes.Count == 2); 
     } 

     [TestMethod] 
     public void SingleLevelXpathTest()  // works 
     { 
      var query = "//form[@id='aspnetForm']"; 
      var documentNode = GetHtmlDocumentNode(); 

      var formNode = documentNode.SelectSingleNode(query); 

      Assert.IsNotNull(formNode); 
     } 

    } 
} 
+0

.NET已建成的XPath,直接用于通过HtmlAgilityPack(HAP没有实现自己的XPath引擎)。实际上,HAP的XPath对我来说工作得很好,所以我建议先怀疑别的东西。 – har07

+0

尝试保存'HtmlDocument',然后检查保存的文件是否包含预期的HTML格式。 – har07

+1

@ har07,它包含 - 我发布之前测试过的问题。此外,“肮脏的解决方法”方法的作品,所以它绝对不是输入问题。增加了测试代码来提问,这样你就可以自己测试它 - 它不像预期的那样工作。 – rufanov

回答

4

在测试中意外的行为发生,因为HTML包含<form>元素:

UPDATE:测试代码。下面是相关讨论:

Ariman:“我发现,分析任何节点没有任何子节点之后所创建的形式应为(,,等)内的所有节点,因为它是。兄弟姐妹而不是孩子

VikciaR: “在HTML规范的表单标签可以重叠,所以Htmlagilitypack处理这个节点有点不同......”

[CodePlex discussion : No child nodes for FORM objects]

而且通过VikciaR还有的建议,尝试修改你的测试代码初始化是这样的:

private static HtmlNode GetHtmlDocumentNode() 
{ 
    var document = new HtmlDocument(); 
    document.LoadHtml(html); 

    //execute this line once 
    HtmlNode.ElementsFlags.Remove("form"); 

    return document.DocumentNode; 
} 

边注:测试方法TwoSingleLevelXpathsTest()inputQuery值应为.//input。请注意开头的点(.)以指示此查询与当前节点相关。否则,它会从根本上进行搜索,忽略前者formQuery(不点,你可以改变formQuery到任何东西,只要它没有返回null,则inputQuery总是会返回相同的结果)。

+2

默认情况下有点奇怪的行为..但无论如何,谢谢!有用! – rufanov