Linq для преобразования коллекции объектов со свойствами xml в коллекцию объектов, представляющих элементы xml?

У меня есть IEnumerable<Item>, где Item имеет свойство с именем «виджеты», которое содержит xml в виде строки. XML-файл содержит элементы для каждого виджета, и каждый виджет может содержать необязательный элемент с именем «foo». Например:

<widgets>
    <widget code="A">
        <foo>1</foo>
    </widget>
    <widget code="B" />
</widgets>

Могу ли я сгладить IEnumerable<Item> в IEnumerable анонимного типа, представляющего виджет?


person adam0101    schedule 13.08.2012    source источник
comment
Итак, вы говорите взять каждый элемент IEnumerable<Item> и вернуть новый IEnumerable<a'>, который содержит все элементы <widget /> из XML как отдельные элементы?   -  person Tejs    schedule 14.08.2012
comment
Да, и в идеале я также хотел бы, чтобы пара свойств анонимного типа заполнялась из свойств элемента.   -  person adam0101    schedule 14.08.2012
comment
Вы ищете что-то вроде select new { ItemName = item.Name, WidgetCodes = widgetCodesFromXml, Foos = foosFromXml }, где Widget и Foos — это IEnumerable‹строка›, содержащая значения, полученные из Xml, или вместо этого select new { ItemName = item.Name, WidgetXmlElements = widgetXmlElements }, где WidgetXmlElements — это IEnumerable‹XElement›, полученные из элементов виджета?   -  person JamieSee    schedule 14.08.2012


Ответы (1)


Я не уверен, может ли foo быть повторяющимся элементом или нет, но в этом случае он возвращается как Enumerable<String>, который достаточно просто изменить.

Настройка (здесь два элемента, с одним и тем же Widgets XML):

public class Item
{
    public string Name;
    public string Widgets;
}

var xml = "<widgets>\r\n    <widget code=\"A\">\r\n        <foo>1</foo>\r\n    </widget>\r\n    <widge" +
"t code=\"B\" />\r\n</widgets>";

var item1 = new Item {Name = "I1", Widgets = xml};
var item2 = new Item {Name = "I2", Widgets = xml};
var items = new Item[] {item1, item2}.AsEnumerable();

Процесс выбора виджета:

var widgets = 
    from item in items
    from widget in XElement.Parse(item.Widgets).Elements("widget")
    select new {
        Name = item.Name,
        Code = widget.Attribute("code").Value,
        Foo = widget.Elements("foo").Select(f => f.Value)
    };

Это дает вам 4 элемента (I1 A, I1 B, I2 A, I2 B) с правильно установленными именами (из элемента) и кодом и Foo (из XML).

Если вы хотите, чтобы foo был одним элементом, изменение выглядит следующим образом (установка FirstOrDefault в основном), что даст вам нули, когда foo нет рядом:

var widgets = 
    from item in items
    from widget in XElement.Parse(item.Widgets).Elements("widget")
    select new {
        Name = item.Name,
        Code = widget.Attribute("code").Value,
        Foo = widget.Elements("foo").Select(f => f.Value).FirstOrDefault()
    };
person yamen    schedule 13.08.2012