2013-08-28 3 views
0

Учитывая ниже DTO определений:Родитель/Дети Xml в DTO модели объекта с помощью LINQ

[Serializable] 
internal class OrderCollection : List<Order> 
{ } 

[Serializable] 
internal class Order 
{ 
    public string OrderId { get; set; } 
    public OrderDetailCollection OrderDetails { get; set; } 
} 


[Serializable] 
internal class OrderDetailCollection : List<OrderDetail> 
{ } 

[Serializable] 
internal class OrderDetail 
{ 
    internal OrderDetail() 
    { 
    } 

    /*public string ParentOrderId { get; set; }*/ 
    public string ItemName { get; set; } 
    public int Quantity { get; set; } 
} 

и следующий XML:

<root> 
    <orders> 

     <order orderId="ABC123"> 
      <orderDetails> 

       <orderDetail itemName="Bike" quantity="1"/> 
       <orderDetail itemName="TeddyBear" quantity="2"/> 
       <orderDetail itemName="Doll" quantity="3"/> 

      </orderDetails> 
     </order> 
     <!-- --> 
     <order orderId="DEF234"> 
      <orderDetails> 

       <orderDetail itemName="Truck" quantity="4"/> 
       <orderDetail itemName="Marbles" quantity="5"/> 
       <orderDetail itemName="BoardGame" quantity="6"/> 

      </orderDetails> 
     </order> 

    </orders> 
</root> 

Есть ли способ, чтобы заполнить всю модель объекта (в результате в одном объекте типа OrderCollection с использованием Linq ..... и в «одном проходе»?

Вот что у меня есть ........ (Я могу получить «заказ (ы)», ...... но не уверен, как получить детей? Или мне нужно взять 2 pas ses на нем, а затем «сопоставить их»?

XDocument xDoc = XDocument.Load(fullFileName); 

    //XNamespace ns = XNamespace.Get("http://schemas.microsoft.com/developer/msbuild/2003"); 
    string ns = string.Empty; 

    List<Order> lineItems = new List<Order> 
    (
      from list in xDoc.Descendants(ns + "orders") 
      from item in list.Elements(ns + "order") 
      where item != null 
      select new Order 
      { 
       OrderId = item.Attribute("orderId") == null ? string.Empty : item.Attribute("orderId").Value 
      } 
     ); 


    OrderCollection returnCollection = new OrderCollection(); 
       returnCollection.AddRange(lineItems); 
+1

О структура XML - я думаю, вы можете поместить элементы 'orderDetail' непосредственно под элементами' order'; вы можете извлечь только элементы 'orderDetail', используя' item.Elements ("orderDetail") '. Кроме того, если у вас есть что-то еще в элементе 'root' кроме элемента' orders', вы можете использовать 'orders' в качестве корневого элемента. –

+0

Хорошо. Во-первых, это необузданный пример xml, который я должен проанализировать. Во-вторых, у меня нет контроля над входным xml. Но спасибо за предложение. – granadaCoder

ответ

1

Попробуйте это:

internal class OrderDetailCollection : List<OrderDetail> 
{ 
    internal OrderDetailCollection() {} 
    internal OrderDetailCollection(IEnumerable<OrderDetail> src) 
    { 
     AddRange(src); 
    } 
} 

List<Order> lineItems = new List<Order> 
(
    from list in xDoc.Descendants(ns + "orders") 
    from item in list.Elements(ns + "order") 
    where item != null 
    select new Order 
    { 
     //note that the cast is simpler to write than the null check in your code 
     //http://msdn.microsoft.com/en-us/library/bb387049.aspx 
     OrderId = (string)item.Attribute("orderId"), 
     OrderDetails = new OrderDetailCollection(
      from detail in item.Descendants("orderDetail") 
      select new OrderDetail { 
       ItemName = (string)detail.Attribute("itemName"), 
       Quantity = (int)detail.Attribute("quantity") 
      } 
     ) 
    } 
); 

Если вам не нужны отдельные классы для коллекций, и может использовать List<Order> и List<OrderDetails> вместо этого, то вы можете сделать это:

List<Order> lineItems = new List<Order> 
(
    from list in xDoc.Descendants(ns + "orders") 
    from item in list.Elements(ns + "order") 
    where item != null 
    select new Order 
    { 
     OrderId = (string)item.Attribute("orderId"), 
     OrderDetails = (
      from detail in item.Descendants("orderDetail") 
      select new OrderDetail { 
       ItemName = (string)detail.Attribute("itemName"), 
       Quantity = (int)detail.Attribute("quantity") 
      } 
     ).ToList() 
    } 
); 
+0

Одна небольшая коррекция (в противном случае спот-ответ) ..... из деталей в item.Elements ("orderDetail") .... Я использовал .. из деталей в item.Elements ("orderDetails"). («orderDetail») СПАСИБО! – granadaCoder

+1

@granadaCoder Исправлено использование '.Descendants' вместо' .Elements'. –

Смежные вопросы