在一个组织不太好的xml中对Linq进行分组

时间:2011-12-13 13:27:08

标签: linq windows-phone-7 linq-to-xml yql

我使用YQL获取一些数据,这是我的xml:

<?xml version="1.0" encoding="UTF-8"?>
<div id="content>
<div id="html">
<h3>City</h3>
<div id="movie">
    <h4>
        <a href="">movie 1</a>
    </h4>
<div>
<div id="movie>
    <h4>
        <a href="">movie 2</a>
    </h4>
</div>
    .
    .
    .

<h3>City 2</h3>
<div id="movie">
    <h4>
        <a href="">movie 1</a>
    </h4>
<div>
<div id="movie>
    <h4>
        <a href="">movie 2</a>
    </h4>
</div>

我想在我的Windows手机应用中使用城市名称及其电影填充列表框,如下所示:

City 1
Movie1
Movie 2

City 2
Movie1
Movie 2

然而,由于所有的XML都在id内容的div中,所以我被困在这里。

如何制作LINQ语句来解决这个问题?

1 个答案:

答案 0 :(得分:1)

我尝试将发布的输入转换为格式良好的XML:

<div id="content">
  <div id="html">
    <h3>City</h3>
    <div id="movie">
      <h4>
        <a href="">movie 1</a>
      </h4>
    </div>
    <div id="movie">
      <h4>
        <a href="">movie 2</a>
      </h4>
    </div>
    .
    .
    .

    <h3>City 2</h3>
    <div id="movie">
      <h4>
        <a href="">movie 1</a>
      </h4>
    </div>
    <div id="movie">
      <h4>
        <a href="">movie 2</a>
      </h4>
    </div>
  </div>
</div>

然后你可以获得一个包含代码的List

    XDocument doc = XDocument.Load("input.xml");
    List<string> data =
        doc.Descendants("h3")
        .Union(
          doc.Descendants("div")
          .Where(d => (string)d.Attribute("id") == "movie")
          .Elements("h4")
          .Elements("a")
          ).InDocumentOrder()
        .Select(e => e.Value)
        .ToList();

[edit]你的初始请求似乎要求提供一个平面列表结果,你的评论建议你想要一个分组结构,所以这里是一个改编的样本:

    XDocument doc = XDocument.Load("input.xml");
    var groupedData =
        (from movie in doc.Root.Descendants("div")
         where (string)movie.Attribute("id") == "movie"
         group movie by movie.ElementsBeforeSelf("h3").Last() into g
         select new
         {
             city = g.Key.Value,
             movies = (from m in g
                       select (string)m.Element("h4").Element("a")).ToList()
         }).ToList();

    // now use above list for data binding or 
    // in the simplest case just consume it with foreach:
    foreach (var group in groupedData)
    {
        Console.WriteLine("city: {0}:", group.city);
        foreach (var movie in group.movies)
        {
            Console.WriteLine(movie);
        }
    }