2012-10-07 22 views
0

我有一個問題,我似乎無法在這裏解決。可以說我在這裏有一些像beneth這樣的html,我想解析。所有這些html都在頁面上的一個列表中。這些名字就像我寫的例子一樣重複着自己。重複僅發生幾次,並與htmlagilitypack C#不同值的對象。

<li class = "seperator"> a date </li> 
<li class = "lol"> some text </li> 
<li class = "lol"> some text </li> 
<li class = "lol"> some text </li> 

<li class = "seperator"> a new date </li> 
<li class = "lol"> some text </li> 


<li class = "seperator"> a nother new date </li> 
<li class = "lol"> some text </li> 
<li class = "lol"> some text </li> 

我確實設法使用htmlagility包來解析每個li對象,並且幾乎是按照我的想法來格式化它。我打印ATM看起來是這樣的:

"a date" "some text" 
"some text" 
"some text" 
"some text" 

"a new date" "some text" 

"a nother new date " "some text" 
"some text" 
"some text" 

我想要什麼才達到:

"a date" "some text" 
"a date" "some text" 
"a date" "some text" 
"a date" "some text" 

"a new date" "some text" 

"a nother new date " "some text" 
"a nother new date " "some text" 
"a nother new date " "some text" 

但問題是,每一個分隔符下方,每一個笑的對象的數量可能會有所不同。所以有一天,網頁可能有一個笑話對象,它的日期是1,第二天它可能有10個笑話對象。所以我很沮喪,如果有一種智能/簡單的方法來計算分離器之間的大聲笑對象的數量。或者如果有另一種方法來解決這個問題呢?以htmlagilitypack爲例。是的,我需要在每一個笑話對象面前都有正確的日期,而不僅僅是第一個面前。這將是蛋糕的PICE如果分隔符類將結束最後笑的對象之下,但可悲的是不是這樣的......我不認爲我需要在這裏貼上我的代碼,但basicly什麼,我要做的就是解析頁面,提取分隔符和lol對象並將它們添加到列表中,在那裏我將它們分割爲分隔符和lol對象。然後我把它打印到一個文件中,由於分隔符只出現3次(在這個例子中),我只會得到3個不同的日期。

回答

0

這裏的計劃,選擇所有seperator元素,然後找到所需的類的所有連續的兄弟元素。

不幸的是,有沒有簡單的方法來獲取HTML敏捷性包的當前版本的兄弟姐妹的集合,你只能訪問到(一個)一個同級。 LINQ很難從鏈接結構中很好地收集數據。而且由於HTML中沒有真正的層次結構,這將是一個挑戰。

如果你的XPath可用,您可以使用following-sibling軸拿到結合下面的所有兄弟元素與TakeWhile()方法來做到以下幾點:

var htmlStr = @"<li class = ""seperator""> a date </li> 
<li class = ""lol""> some text </li> 
<li class = ""lol""> some text </li> 
<li class = ""lol""> some text </li> 

<li class = ""seperator""> a new date </li> 
<li class = ""lol""> some text </li> 


<li class = ""seperator""> a nother new date </li> 
<li class = ""lol""> some text </li> 
<li class = ""lol""> some text </li>"; 

var doc = new HtmlDocument(); 
doc.LoadHtml(htmlStr); 
var data = 
    from li in doc.DocumentNode.SelectNodes("li[@class='seperator']") 
    select new 
    { 
     Separator = li.InnerText, 
     Content = li.SelectNodes("following-sibling::li") 
      .TakeWhile(sli => sli.Attributes["class"].Value == "lol") 
      .Select(sli => sli.InnerText) 
      .ToList(), 
    }; 

否則,如果你沒有XPaths可用,您可以使用以下任何鏈接結構創建枚舉:

public static class Extensions 
{ 
    public static IEnumerable<TSource> ToLinkedEnumerable<TSource>(
     this TSource source, 
     Func<TSource, TSource> nextSelector, 
     Func<TSource, bool> predicate) 
    { 
     for (TSource current = nextSelector(source); 
       predicate(current); 
       current = nextSelector(current)) 
      yield return current; 
    } 

    public static IEnumerable<TSource> ToLinkedEnumerable<TSource>(
     this TSource source, Func<TSource, TSource> nextSelector) 
     where TSource : class 
    { 
     return ToLinkedEnumerable(source, nextSelector, src => src != null); 
    } 
} 

然後,您的查詢現在變成這樣的:

var data = 
    from li in doc.DocumentNode.Elements("li") 
    where li.Attributes["class"].Value == "seperator" 
    select new 
    { 
     Separator = li.InnerText, 
     Content = li.ToLinkedEnumerable(sli => sli.NextSibling) 
      .Where(sli => sli.Name == "li") 
      .TakeWhile(sli => sli.Attributes["class"].Value == "lol") 
      .Select(sli => sli.InnerText) 
      .ToList(), 
    }; 
+0

感謝你的小費!我認爲這會幫助我解決我的問題! :) – dtd