如何选择包含某些关键字的表 - c# - xpath - htmlagilitypack

时间:2011-12-25 23:25:16

标签: c# select xpath html-agility-pack keyword

我必须从没有任何课程或ID的产品页面收集信息。我正在使用htmlagilitypack和c#4.0。

此产品页面源代码中有许多表格。价格表包含“KDV”字符串。所以我想得到这个包含表格的“KDV”字符串。我怎么能这样做?

下面的xpath将选择所有表格,例如

string srxPathOfCategory = "//table";
var selectedNodes = myDoc.DocumentNode.SelectNodes(srxPathOfCategory);

下面的代码选择表,但从大多数外表开始。我需要选择包含给定字符串

的大多数内部表
//table[contains(., ' KDV')]

c#,xpath,htmlagilitypack

2 个答案:

答案 0 :(得分:4)

  

下面的代码选择表,但从大多数外表开始。一世   需要选择包含给定字符串的大多数内部表

使用

//table
    [not(descendant::table) 
   and 
     .//text()[contains(., ' KDV')]
    ]

这将选择XML文档中没有table后代的任何table,并且该文本节点后代包含字符串" KDV"

通常,上面的表达式可以选择许多这样的table元素。

如果您只想选择其中一个(比如第一个),请使用此XPath表达式 - 请注意括号

   (//table
        [not(descendant::table) 
       and 
         .//text()[contains(., ' KDV')]
        ]
    )[1]

记住:如果要选择文档中的第一个someName元素,使用此元素(如当前接受的答案中)是错误的:

//someName[1]

这是XPath中第二个最常见的FAQ(在使用默认命名空间的XML文档中如何选择带有无前缀名称的元素之后)。

上面的表达式实际上选择了文档中的任何someName元素,即父元素的第一个子元素 - 尝试它。

这种不直观行为的原因是因为XPath []运算符的优先级(优先级)高于//伪运算符。

真正选择第一个someName元素(在任何XML文档中)的正确表达式(如果存在)是:

(//someName)[1]

此处括号用于显式覆盖默认的XPath运算符优先级。

答案 1 :(得分:1)

可能有一种更有效的方法。无论如何, 这是我用于你的案例的整个代码,它适用于我:

        HtmlDocument doc = new HtmlDocument();
        string url = "http://www.pratikev.com/fractalv33/pratikEv/pages/viewProduct.jsp?pInstanceId=3138821";
        using (var response = (WebRequest.Create(url).GetResponse()))
        {
            doc.LoadHtml(new StreamReader(response.GetResponseStream()).ReadToEnd());
        }
        /*There is an bug in the xpath used here. Should have been 
          (//table/tr/td/font[contains(.,'KDV')])[1]/ancestor::table[2] 
          See Dimitre's answer for an explanation and an alternative / 
          more generic / (needless to say) better approach */
        string xpath = "//table/tr/td/font[contains(.,'KDV')][1]/ancestor::table[2]"; 
        HtmlNode table = doc.DocumentNode.SelectSingleNode(xpath);