2013-02-21 4 views
28

누군가가 나를 도울 수 있기를 바랍니다. HTML 문서를 얻을 수 HtmlAgilityPack를 사용하여HtmlAgilityPack 및 노드 및 하위 노드 선택

<div class="search_hit"> 

    <span prop="name">Richard Winchester</span> 
    <span prop="company">Kodak</span> 
    <span prop="street">Arlington Road 1</span> 

</div> 
<div class="search_hit"> 

    <span prop="name">Ted Mosby</span> 
    <span prop="company">HP</span> 
    <span prop="street">Arlington Road 2</span> 

</div> 

미안 :

Let's 내가이 예와 같이 여러 div에 포함 된 HTML 문서를 말한다. 내가 알아야 할 것은 어떻게 각각의 "search_hit"-div에 걸쳐 범위를 얻을 수 있습니까?

foreach (HtmlAgilityPack.HtmlNode node in doc.DocumentNode.SelectNodes("//div[@class='search_hit']")) 
{ 
    foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes("//span[@prop]")) 
    { 

    } 
} 

각 사업부는 개체가 속성으로 포함 스팬과 함께해야

내 첫번째 생각은 다음과 같이이었다. I. e.

public class Record 
    { 
     public string Name { get; set; } 
     public string company { get; set; } 
     public string street { get; set; } 
    } 

이 목록

는 채워 져야한다

public List<Record> Results = new List<Record>(); 

그러나이 사용 XPATH의 미안 그것이 무엇을해야으로 하위 노드에서 검색을 수행하지 않습니다. 그것은 전체 문서를 반복해서 검색한다는 점에서 이음새가 없습니다.

나는 그것이 이미 전체 페이지의 범위를 얻을 수있는 방식으로 작업하고 있다는 것을 의미합니다. 그러나 그때 나는 span과 div 사이의 관계가 없습니다. 의미 : 어떤 스팬이 어느 div와 관련되는지 더 이상 알지 못합니다.

누군가 해결책을 알고 있습니까? 나는 이미 그 정도로 놀았으나 지금은 완전히 혼란스러워하고있다. :)

어떤 도움을 주실 수 있나요?

+0

코드를 구문 분석하는 방법에 대한 답변을 참조하십시오 (전체 작동 솔루션). –

답변

24

다음 작품. 중요한 비트는 BeniBela가 'SelectNodes'에 대한 두 번째 호출에서 점을 추가한다고 언급 한 것과 같습니다.

모든
List<Record> lstRecords=new List<Record>(); 
foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//div[@class='search_hit']")) 
{ 
    Record record=new Record(); 
    foreach (HtmlNode node2 in node.SelectNodes(".//span[@prop]")) 
    { 
    string attributeValue = node2.GetAttributeValue("prop", ""); 
    if (attributeValue == "name") 
    { 
     record.Name = node2.InnerText; 
    } 
    else if (attributeValue == "company") 
    { 
     record.company = node2.InnerText; 
    } 
    else if (attributeValue == "street") 
    { 
     record.street = node2.InnerText; 
    } 
    } 
    lstRecords.Add(record); 
} 
42

//을 사용하면 문서 시작에서 검색을 시작합니다.

사용 .// 현재 노드

foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes(".//span[@prop]")) 

에서 모든 검색하거나 직접 아이들을 검색 전체 접두사를 떨어 뜨리지 : 나를 위해

foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes("span[@prop]")) 
+0

내가 이렇게하면 : node.SelectNodes ("span [@prop]")의 foreach (HtmlAgilityPack.HtmlNode node2) Visual Studio에서 오류가 발생합니다. –

+0

어떤 종류의 오류입니까? '. /'접두사를 사용해도 좋다. (나는 실제로 그냥 짐작하고있다) – BeniBela

+0

나는 둘 다 시도하고 모두 함께 끝날 : NullReferenceException : 개체 참조가 개체의 인스턴스로 설정되지 않았습니다. –

2

우선, 이것 좀보세요 : 여기 Html Agility Pack - Problem selecting subnode

귀하의 질문에 대한 전체 작업 솔루션입니다 :

IList<Record> results = new List<Record>(); 
foreach (var node in doc.DocumentNode.SelectNodes("//div[@class='search_hit']")) { 
    var record = new Record(); 
    record.Name = node.SelectSingleNode(".//span[@prop='name']").InnerText; 
    record.company = node.SelectSingleNode(".//span[@prop='company']").InnerText; 
    record.street = node.SelectSingleNode(".//span[@prop='street']").InnerText; 
    results.Add(record); 
} 

당신은 내가 당신을 가리키는 질문을 읽으면 span 노드는 div 노드의 (직접적인) 하위 노드이기 때문에 ./span[@prop='name']을 수행하는 것이 완전히 동일하다는 것을 알 수 있습니다.span 노드가 그 prop 속성을 가지고 있지 않으며, 당신은 그들이 나타나는 순서에 따라 지정하려면


, 당신은 할 수 있습니다 :

foreach (var node in doc.DocumentNode.SelectNodes("//div[@class='search_hit']")) { 
    var spanNodes = node.SelectNodes("./span"); 
    var record = new Record(); 
    record.Name = spanNodes[0].InnerText; 
    record.company = spanNodes[1].InnerText; 
    record.street = spanNodes[2].InnerText; 
    results.Add(record); 
} 
2

부끄러운 날에 :)

여러분 모두가 옳았습니다.

문제점을 발견했습니다. 이 NullReferenceException은 계속 잔소리를하면서 계속 자세히 보았습니다. 모든 div 사이에는 같은 "class = 'search-hit'"속성을 가진 하나의 div가 있지만 내부에는 span이 없습니다. 그게 왜 두 번째 루프에서 오류를 통과했는지.

foreach (HtmlAgilityPack.HtmlNode node in doc.DocumentNode.SelectNodes("//span[@prop]/ancestor::div[@class='search_hit']")) 
    { 
     Record rec = new Record(); 
     foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes(".//span[@prop]")) 
      { 
      } 
      rList.Results.Add(rec); 
    } 

위의 코드가 작동합니다.

시간을내어 도와 주셔서 감사합니다.

0

나는 그것을 사용했다. 클래스로 변환 ID

HtmlNodeCollection nodes = dokuman.DocumentNode.SelectNodes("//div[@id='search_hit']//span[@prop]"); 


      for (int i = 0; i < nodes .Count; i++) 
     { 
      var record = new Record(); 


       record.Name = links[i].InnerText; results.Add(record); }