【问题标题】:How to Bind HTML Parse (HAP) to ListBox DataTemplate如何将 HTML Parse (HAP) 绑定到 ListBox DataTemplate
【发布时间】:2011-09-05 02:18:17
【问题描述】:

我目前正在运行以下代码,以使用适用于 WP7 的 HTML Agility Pack 解析 HTML 链接。

编辑 ******************************** 带有建议更改的代码

void client_DownloadStringCompleted(对象发送者,Dow​​nloadStringCompletedEventArgs e) { var html = e.Result;

var doc = new HtmlDocument();
    doc.LoadHtml(html);

var list = doc.DocumentNode.Descendants("div").ToList();


var node = doc.DocumentNode.Descendants("div")
    .FirstOrDefault(x => x.Id == "FlightInfo_FlightInfoUpdatePanel")
    .Element("table")
    .Element("tbody")
    .Elements("tr").Select(n => new Flight()
    {
        Airline = n.Element("td").Single(j => j.Attribute("class") == "airline").Value,
        FlightType = n.Element("td").Single(j => j.Attribute("class") == "airline").Value,
        Time = n.Element("td").Single(j => j.Attribute("class") == "airline").Value,
    }

    );

这会将以下内容输出到滚动查看器中

每行中有多个 td 用于航班、时间、航空公司等。我想做的是将每个 td 内部文本绑定到列表框数据模板。

这是我认为 XAML 的示例

<ListBox Margin="6,6,-12,0" Name="listBox1">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Margin="0,0,0,17" Width="432" Height="Auto">

                            <TextBlock Text="{Binding Airline}" Foreground="#FF4BCCF5" FontSize="24" />
                            <TextBlock Text="{Binding Flight}" TextWrapping="Wrap" FontSize="22" Foreground="#FF969696" />
                            <TextBlock Text="{Binding Time}" TextWrapping="Wrap" FontSize="20" Foreground="#FF05C16C" />
                            <TextBlock Text="{Binding Origin}" TextWrapping="Wrap" FontSize="20" />
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

HTML 示例:

 <tr class="">
 <td class="airline"><img src="/images/airline logos/NZ.gif" title="AIR NEW ZEALAND LIMITED. " alt="AIR NEW ZEALAND LIMITED. " /></td>
 <td class="flight">NZ8</td>
 <td class="codeshare">&nbsp;</td>
 <td class="origin">San Francisco</td>
 <td class="date">01 Sep</td>
 <td class="time">17:15</td>
 <td class="est">18:00</td>
 <td class="status">DEPARTED</td>
 </tr>

所以问题是:如何将每个 td 结果绑定到自己的文本块?

【问题讨论】:

  • 你能展示一个更好的 Html 例子吗?
  • 每个 td 上有什么?你发布的图片被剪掉了。
  • @Derek 我刚刚更新了我的代码。
  • @alfonsa 只更新 HTML 部分

标签: c# html parsing windows-phone-7 html-agility-pack


【解决方案1】:
public class Flight
{    
    public string Airline { get; set; }
    public string Flight { get; set; }
    public DateTime Time { get; set; }    
}

这是你的代码:

var node = doc.DocumentNode.Descendants("div")
        .FirstOrDefault(x => x.Id == "FlightInfo_FlightInfoUpdatePanel")
        .Element("table")
        .Element("tbody")
        .Elements("tr").Aggregate("Flight list\n", (acc, n) => acc + "\n" + n.OuterHtml);

之后

List<Flight> flightList=new List<Flight>();
foreach (HtmlNode tr in node){
    flightList.Add(new Flight(){    
        Airline=tr.Descendants("td")
            .FirstOrDefault(f=>f.Attributes["class"].Value=="airline").InnerHtml,
        Flight=tr.Descendants("td")
            .FirstOrDefault(f=>f.Attributes["class"].Value=="flight").InnerText
// Insert other properties here
    });    
}

listbox1.ItemsSource=flightList;

【讨论】:

  • 谢谢,但有几个问题。 Error 1 Cannot convert type 'char' to 'HtmlAgilityPack.HtmlNode' 公共字符串 Flight 与 Flight=tr.Descendants 相同。我已将航班更正为 Flight1,但我不确定 foreach?
  • 自己纠正一些简单的错误。我们只说想法或方法。不要复制粘贴。大多数答案未在编译器中检查
  • 很公平。谢谢你的帮助。你的网站也非常适合 WordPress 的东西。
  • 我问的原因是因为我不知道并且已经为此苦苦挣扎了好几天。我希望你能解释一下。
【解决方案2】:

您可以创建一个绑定到 UI 的简单模型对象:

public class Flight
{    
    public string Airline { get; set; }
    public string Flight { get; set; }
    public DateTime Time { get; set; }    
}

然后使用 Select 投影将您的文档转换为航班列表:

var node = doc.DocumentNode.Descendants("div")
    .FirstOrDefault(x => x.Id == "FlightInfo_FlightInfoUpdatePanel")
    .Element("table")
    .Element("tbody")
    .Elements("tr").Aggregate("Flight list\n", (acc, n) => acc + "\n" + n.OuterHtml);

List<Flight> flights = node.Elements("td").Select(i =>
           new Flight()
           {
              Airline = i.Element("td").Single(j => j.Attribute("class") == "airline").Value,
              Flight = i.Element("td").Single(j => j.Attribute("class") == "flight").Value,
              ...
           }

然后将此 Flight 实例列表绑定到您的 UI。

我对 HTML Agility Pack 不熟悉,所以我假设它的 Linq API 与 Linq to XML 相似或相同。您可能需要稍微调整一下上面的查询代码,但一般的方法应该没问题。

【讨论】:

  • 我在想一个类似的方法,但没有 node.Elements 只有 ElementAt 或 ElementAtOrDefault。您还缺少 .Select(i => ....? 的右括号吗?
  • @Rhys 只需将聚合替换为 Select(n=> new Flight...)。我在您的第一个问题中选择聚合的部分原因是我预计您可能需要投影结果而不是简单地打印它们。
  • @Rune FS 我已经进行了请求的更改,但 HTML 敏捷包没有单一的定义。还有什么想法吗?
  • @rhys 使用 xpath 而不是 "//[@class=airline]" 节点的一种方法接受 xpath
  • @Rune FS 我认为 HTML Agility Pack 不支持 XPath?我知道这很痛苦,但是您是否有机会为我提供一些代码,以便我更好地理解。再次感谢。
猜你喜欢
  • 2011-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-24
  • 1970-01-01
相关资源
最近更新 更多