вложенный xml с linq в повторителе

У меня есть XML-файл, который выглядит так, и я пытаюсь получить все атрибуты местоположения в ячейке таблицы. Мне удалось получить название и описание, но почему-то не удалось получить все места внутри событий.

Может ли кто-нибудь помочь мне в этом?

Привет Терри

То, что я придумал до сих пор, следующее

var qListCurrentMonth = (from feed in doc.Descendants("item")
                         select new
                        {
                            title = feed.Element("title").Value,
                            description = feed.Element("description").Value,
                            events = (from ev in feed.Element("events").Elements("location")
                                      select new
                                                 {
                                                     city = ev.Attribute("city")
                                                 }).ToList()
                        });

rptFeedItems.DataSource = qListCurrentMonth;
rptFeedItems.DataBind();

а тут xml

События Модный показ 1

  <description>item  descr</description>
  <link>http://somelink</link>

  <events>
    <location city="nyc" date="12.12.08" link="http://www.etc.com" />
    <location city="nyc" date="25.11.08" link="http://www.etc.com" />
    <location city="sfo" date="11.11.08" link="http://www.etc.com" />
    <location city="sfo" date="22.01.08" link="http://www.etc.com" />
    <location city="dal" date="12.12.08" link="http://www.etc.com" />

  </events>
</item>

<item>
  <title>Fashion show 2</title>

  <description>item  descr</description>
  <link>http://somelink</link>

  <events>
    <location city="nyc" date="12.12.08" link="http://www.etc.com" />
    <location city="nyc" date="25.11.08" link="http://www.etc.com" />
    <location city="sfo" date="11.11.08" link="http://www.etc.com" />
    <location city="sfo" date="22.01.08" link="http://www.etc.com" />
    <location city="dal" date="12.12.08" link="http://www.etc.com" />

  </events>
</item>

а тут повторитель

<table border="1">
           <asp:Repeater runat="server" ID="rptFeedItems">
                <ItemTemplate>
                    <tr>
                        <td><%# Eval("title")%></td>
                        <td><%# Eval("description")%></td>
                        <td><%# Eval("events")%></td>
                    </tr>

                </ItemTemplate>
            </asp:Repeater>

        </table>

person Terry Marder    schedule 01.08.2009    source источник
comment
Рассматривали ли вы возможность использования XSLT? :-)   -  person mmx    schedule 01.08.2009
comment
Я не могу представить себе случай, когда кто-то захочет использовать XSLT, если он может использовать LINQ to XML. При этом есть законные причины для XSLT, например, когда необходимо взаимодействие с системами, отличными от .NET, и когда преобразование должно быть предоставлено системе на более позднем этапе, и разрешение LINQ to XML может быть угрозой безопасности, поскольку его можно использовать для внедрения произвольного кода.   -  person Stilgar    schedule 01.08.2009


Ответы (2)


Я предполагаю, что вы получаете общий тип списка вместо значения элемента. Это связано с тем, что Eval возвращает результат ToString(), а ToString() в списке возвращает тип. Есть несколько вещей, которые вы можете сделать. Один из них вкладывает другой повторитель и привязывает его к свойству событий. Это самое чистое решение в теории, хотя в данном случае я сомневаюсь, что оно того стоит.

Еще одна вещь, которую вы можете сделать, это накопить свойство events в виде строки. это можно сделать так:

var qListCurrentMonth = 
    (from feed in doc.Descendants("item")
     select new 
     {
         title = feed.Element("title").Value,
         description = feed.Element("description").Value,
         events = 
            (from ev in feed.Element("events").Elements("location")
             select ev.Attribute("city").Value).Aggregate((x,y) => x+ "<br />" + y)
      });

Метод Aggregate будет накапливать коллекцию в одном экземпляре. Если у вас есть более 5 событий в среднем на строку, вам лучше использовать StringBuilder в качестве аккумулятора (существует перегрузка Aggregate) по соображениям производительности (я уверен, что вы знаете о строке против StringBuilder и производительности).

Поскольку вы используете .NET 3.5, я бы посоветовал использовать ListView вместо Repeater... как всегда. Также в этом случае GridView может быть лучше, поскольку вы представляете таблицу.

Наконец, следуйте соглашению .NET и используйте PascalCase для имен свойств (т.е. Events вместо Events)

person Stilgar    schedule 01.08.2009
comment
Большое спасибо, Стилгар, я бы никогда не подумал об использовании агрегированного метода. - person Terry Marder; 04.08.2009

Если вы просто хотите перечислить коды городов в ячейке событий:

var qListCurrentMonth =
    from feed in doc.Descendants("item")
    let cities =
        (from location in feed.Element("events").Elements("location")
         select location.Attribute("city").Value)
         .ToArray())
    select new
    {
        title = feed.Element("title").Value,
        description = feed.Element("description").Value,
        events = string.Join(", ", cities)
    });

Агрегатный метод Стилгара также является отличным предложением.

person Joe Chung    schedule 02.08.2009