Синтаксис LINQ To XML для XML-элемента с атрибутами - PullRequest
2 голосов
/ 14 мая 2009

Я немного новичок в LINQ, и у меня возникли некоторые проблемы со следующим. Я пытаюсь выполнить запрос с помощью LINQ для файла XML и сохранить результаты в списке объектов DataClass, соответствующих XML.

У меня есть XML-файл, который определен так:

<NewDataSet>
    <NewDataTable>
      <Field>Accepted ASNs</Field>
      <Val>59</Val>
      <Order Number="1234" ShipDate="2009/05/21" />
      <Order Number="2190" ShipDate="2009/05/22" />
      <Order Number="1809" ShipDate="2009/05/22" />      
    </NewDataTable>
    <NewDataTable>
      <Field>Rejected ASNs</Field>
      <Val>8</Val>
      <Order Number="2901" ShipDate="2009/05/21" />
      <Order Number="2810" ShipDate="2009/05/24" />
      <Order Number="1419" ShipDate="2009/05/25" />
    </NewDataTable>
    <NewDataTable>
      <Field>Missing ASNs</Field>
      <Val>7</Val>
      <Order Number="2902" ShipDate="2009/05/19" />
      <Order Number="2898" ShipDate="2009/05/20" />
      <Order Number="1296" ShipDate="2009/05/22" />
    </NewDataTable>
 </NewDataSet>

Я создал класс данных для поддержки этого формата XML. Я хотел бы создать запрос LINQ, чтобы получить эти 3 записи и сохранить их в списке моего DataClass.

Чтобы поддерживать несколько элементов Order, мой класс определен с помощью общего списка структур "Order" ... Это выглядит так:

    Public Class ASNData
        Private _field As String
        Private _value As String
        Private _orders As List(Of Order)

        Public Property Field() As String
            Get
            Set
        End Property

        Public Property Value() As String
            Get
            Set
        End Property

        Public Property Orders() As List(Of Order)
            Get
            Set
        End Property

        Structure Order
            Private _number As String
            Private _date As Date

            Public Property Number() As String
                Get
                Set
            End Property

            Public Property ShippingDate() As Date
                Get
                Set
            End Property
        End Structure
    End Class

Самая большая проблема, с которой я столкнулся, - это выяснить, как получить 3 элемента заказа и сохранить их в моем списке структур порядка.

Кто-нибудь может указать мне правильное направление на это?

Спасибо.

Ответы [ 4 ]

4 голосов
/ 14 мая 2009

Вот код консольного приложения с нужным вам запросом LINQ. Мне пришлось заполнить геттеры и сеттеры вашего класса и содержащую их структуру, но это проверенный рабочий код. Чтобы получить список (из ASNData), просто вызовите DataTables.ToList

Конечно, это будет работать с любым количеством элементов Order.

Использование Structure Order работает просто отлично. Я бы использовал класс, но не нужно менять его, чтобы это работало.

Ключевой частью этого кода является запрос LINQ:

Dim DataTables = From NewDataTable In TestData...<NewDataTable> _
                 Select New ASNData With {.Field = NewDataTable.<Field>.Value, _
                                          .Value = NewDataTable.<Val>.Value, _
                                          .Orders = (From AnOrder In NewDataTable...<Order> _
                                                     Select New ASNData.Order With _
                                                            {.Number = AnOrder.@Number, _
                                                             .ShippingDate = Date.Parse(AnOrder.@ShipDate)}).ToList}

Вот полное рабочее приложение консоли:

Module Module1

Sub Main()
    Dim TestData = <NewDataSet>
                       <NewDataTable>
                           <Field>Accepted ASNs</Field>
                           <Val>59</Val>
                           <Order Number="1234" ShipDate="2009/05/21"/>
                           <Order Number="2190" ShipDate="2009/05/22"/>
                           <Order Number="1809" ShipDate="2009/05/22"/>
                       </NewDataTable>
                       <NewDataTable>
                           <Field>Rejected ASNs</Field>
                           <Val>8</Val>
                           <Order Number="2901" ShipDate="2009/05/21"/>
                           <Order Number="2810" ShipDate="2009/05/24"/>
                           <Order Number="1419" ShipDate="2009/05/25"/>
                       </NewDataTable>
                       <NewDataTable>
                           <Field>Missing ASNs</Field>
                           <Val>7</Val>
                           <Order Number="2902" ShipDate="2009/05/19"/>
                           <Order Number="2898" ShipDate="2009/05/20"/>
                           <Order Number="1296" ShipDate="2009/05/22"/>
                       </NewDataTable>
                   </NewDataSet>

    Dim DataTables = From NewDataTable In TestData...<NewDataTable> _
                     Select New ASNData With {.Field = NewDataTable.<Field>.Value, .Value = NewDataTable.<Val>.Value, _
                                                     .Orders = (From AnOrder In NewDataTable...<Order> _
                                                               Select New ASNData.Order With {.Number = AnOrder.@Number, .ShippingDate = Date.Parse(AnOrder.@ShipDate)}).ToList}

    Console.WriteLine(DataTables.Count)
    Console.ReadLine()


End Sub

Public Class ASNData
    Private _field As String
    Private _value As String
    Private _orders As List(Of Order)

    Public Property Field()
        Get
            Return _field
        End Get
        Set(ByVal value)
            _field = value
        End Set
    End Property

    Public Property Value() As String
        Get
            Return _value
        End Get
        Set(ByVal value As String)
            _value = value
        End Set
    End Property

    Public Property Orders() As List(Of Order)
        Get
            Return _orders
        End Get
        Set(ByVal value As List(Of Order))
            _orders = value
        End Set
    End Property

    Structure Order
        Private _number As String
        Private _date As Date

        Public Property Number() As String
            Get
                Return _number
            End Get
            Set(ByVal value As String)
                _number = value
            End Set
        End Property

        Public Property ShippingDate() As Date
            Get
                Return _date
            End Get
            Set(ByVal value As Date)
                _date = value
            End Set
        End Property
    End Structure
End Class


End Module
0 голосов
/ 06 июля 2009
XDocument xmlDoc = XDocument.Load(Server.MapPath("Order.xml"));

List<ASNData> lst= (from data in xmlDoc.Root.Elements("NewDataTable")
    select new ASNData
    {
        Field=data.Element("Field").Value,
        Value=data.Element("Val").Value,
        Orders=(from ord in data.Elements("Order")
        select new Order
        {
            Number=ord.Attribute("Number").Value,
            ShippingDate=Convert.ToDateTime(ord.Attribute("ShipDate").Value)
         }).ToList<Order>()
     }).ToList<ASNData>();

foreach(ASNData a in lst)
{

     Response.Write("Field:"+a.Field+"</br>");
     Response.Write("Value:"+a.Value+"</br>");
     Response.Write("Orders:"+"</br>");

     foreach(Order o in a.Orders)
     {
         Response.Write("OrderNum:"+o.Number+"</br>");
         Response.Write("ShipDate:"+o.ShippingDate+"</br>");
     }
}
0 голосов
/ 14 мая 2009
var result = from order in YourXMLVar.Descendants("NewDataTable")
    .First().Elements("Order") select order;

Это должно дать вам массив заказов.

Тогда вы сможете сделать что-то вроде:

foreach(var order in result)
{
  int someVal = Convert.ToInt32(order.Attribute("Number").Value);
}

// РЕДАКТИРОВАТЬ: Очевидно, вы бы не использовали First (), а вместо этого выполняли бы итерации по вашим приказам или тому, что диктует ваша логика. Я использовал First (), потому что он сделал для простой демонстрации.

0 голосов
/ 14 мая 2009

Чтобы получить элементы заказа (из элемента NewDataTable), вы должны использовать

 newDataTableElement.Elements("Order")

, который вернет IEnumerable<XElement> - затем вы можете использовать Select, чтобы преобразовать каждый как обычно. Чтобы получить атрибуты, используйте:

 element.Attribute("Number").Value
 element.Attribute("ShipDate").Value

Это даст значение для использования в качестве строки - вы можете получить XAttribute, чтобы сделать преобразования для вас, хотя:

 CType(element.Attribute("Number"), Integer)
 CType(element.Attribute("ShipDate"), DateTime)

Я не на 100% уверен, что это сработает для ваших дат, потому что он может ожидать полную дату и время - хотя стоит попробовать. В противном случае просто проанализируйте строку, используя DateTime.ParseExact.

Я бы настоятельно рекомендовал бы вам пересмотреть Order как структуру, особенно - изменчивую структуру. Есть ли причина сделать его структурой, а не классом?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...