我必须从没有任何课程或ID的产品页面收集信息。我正在使用htmlagilitypack和c#4.0。
此产品页面源代码中有许多表格。价格表包含“KDV”字符串。所以我想得到这个包含表格的“KDV”字符串。我怎么能这样做?
下面的xpath将选择所有表格,例如
string srxPathOfCategory = "//table";
var selectedNodes = myDoc.DocumentNode.SelectNodes(srxPathOfCategory);
下面的代码选择表,但从大多数外表开始。我需要选择包含给定字符串
的大多数内部表//table[contains(., ' KDV')]
c#,xpath,htmlagilitypack
答案 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);