带有属性的XML元素的LINQ to XML语法

时间:2009-05-13 21:02:53

标签: xml vb.net linq linq-to-xml

我是一个LINQ新手,我遇到了以下问题。我正在尝试使用XML文件上的LINQ执行查询,并将结果存储在与XML匹配的DataClass对象列表中。

我有一个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>

我创建了一个Data类来支持这种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阶元素并将它们存储到我的Order结构列表中。

有人能指出我正确的方向吗?

谢谢。

4 个答案:

答案 0 :(得分:4)

以下是您需要LINQ查询的Console应用程序的代码。我必须填写你的类的getter和setter并包含结构,但这是经过测试的工作代码。要获取List(Of 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

答案 1 :(得分:0)

要获取订单元素(来自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) 为您进行转换:

DateTime.ParseExact

我不是100%认为这对你的约会有用,因为它可能会有一个完整的日期和时间 - 值得一试。否则,只需使用Order解析字符串。

强烈建议您重新考虑{{1}}作为结构 - 尤其是可变结构。是什么原因使它成为一个结构而不是一个类?

答案 2 :(得分:0)

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>");
     }
}

答案 3 :(得分:-1)

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(),因为它是一个简单的演示。