2011-01-06 103 views
12

解析HTML我有以下的HTML与HTML敏捷性包和LINQ

(..) 
<tbody> 
<tr> 
    <td class="name"> Test1 </td> 
    <td class="data"> Data </td> 
    <td class="data2"> Data 2 </td> 
</tr> 
<tr> 
    <td class="name"> Test2 </td> 
    <td class="data"> Data2 </td> 
    <td class="data2"> Data 2 </td> 
</tr> 
</tbody> 
(..) 

我掌握的信息是名字=>所以 “Test1的” & “的Test2”。我想知道的是,如何根据我的名称获取“data”和“data2”中的数据。

目前我使用:

var data = 
    from 
     tr in doc.DocumentNode.Descendants("tr") 
    from 
     td in tr.ChildNodes.Where(x => x.Attributes["class"].Value == "name") 
    where 
     td.InnerText == "Test1" 
    select tr; 

,但我得到{"Object reference not set to an instance of an object."}当我尝试看看在data

+0

准确地说,你想要做什么?那么你不想要的代码是什么? – 2011-01-06 15:55:56

+0

嘿嘿,抱歉,我忘了添加它,我现在添加它 – 2011-01-06 15:56:50

回答

13

至于你尝试,你有两个问题与您的代码:

  1. ChildNodes是奇怪 - 这也返回空白文本节点,没有class属性(不能有属性,课程)。
  2. 正如詹姆斯沃尔福德所评论的那样,文本周围的空间很重要,你可能想要修剪它们。

有了这两个更正,以下工作:

var data = 
     from tr in doc.DocumentNode.Descendants("tr") 
     from td in tr.Descendants("td").Where(x => x.Attributes["class"].Value == "name") 
    where td.InnerText.Trim() == "Test1" 
    select tr; 
1

这里有一个方法 - 首先分析所有的数据到数据结构,然后读取它。这是一个有点乱,当然需要更多的验证,但这里有云:

HtmlWeb hw = new HtmlWeb(); 
HtmlDocument doc = hw.Load("http://jsbin.com/ezuge4"); 
HtmlNodeCollection nodes = doc.DocumentNode 
           .SelectNodes("//table[@id='MyTable']//tr"); 
var data = nodes.Select(
    node => node.Descendants("td") 
     .ToDictionary(descendant => descendant.Attributes["class"].Value, 
         descendant => descendant.InnerText.Trim()) 
     ).ToDictionary(dict => dict["name"]); 
string test1Data = data["Test1"]["data"]; 

在这里,我把每一个<tr>的字典,其中类的<td>的是键和文字是一个值。接下来,我将字典列表变成字典字典(提示 - 抽象的),其中name的每个是关键。

0

代替

td.InnerText == "Test1" 

尝试

td.InnerText == " Test1 " 

d.InnerText.Trim() == "Test1" 
4

这里是XPATH方式 - 嗯...大家似乎已经忘记了权力XPATH并专门对C#XLINQ,集中这些天:-)

该函数获得与名称相关联的所有数据值:

public static IEnumerable<string> GetData(HtmlDocument document, string name) 
{ 
    return from HtmlNode node in 
     document.DocumentNode.SelectNodes("//td[@class='name' and contains(text(), '" + name + "')]/following-sibling::td") 
     select node.InnerText.Trim(); 
} 

例如,该代码将转储 '的Test2' 的数据:

HtmlDocument doc = new HtmlDocument(); 
    doc.Load(yourHtml); 

    foreach (string data in GetData(doc, "Test2")) 
    { 
     Console.WriteLine(data); 
    }