user3363178
user3363178

Reputation: 3

Trying to parse XML and create a List information using Linq and C#

Very new to C# and Linq, lots to learn... I would like to be able to parse XML with Linq, and move a portion of the XML data into a List. The XML data is small, Initially (query 1 below) I was able to capture all nodes except the ACCT nodes. My 2nd attempt was to create a 2nd query (ACCT query below) but it only successfully captures the 1st occurrence of ACCT . searched for some time, found several examples but I have not been successful in implementing way to capture all occurrences of ACCT with Linq and c#. Seems like a VERY useful tool, any assistance would be appreciated.

here is XML

<?xml version="1.0" encoding="utf-8"?>
<ORDER>
  <EMPNUMBER>LDC</EMPNUMBER>
  <ITEMNAME>NEWNAME_GR0045LDS01.JPG</ITEMNAME>
  <DATETIMESTAMP>04-19-2015</DATETIMESTAMP>
  <DEPT>HMES</DEPT>
<SHIPMENTLIST>
  <ACCT>2222222222</ACCT>
  <ACCT>1111111111</ACCT>
</SHIPMENTLIST>
</ORDER>

here is current class

public class clsShipACCT
{

    public string strShipACCT
    {
        get;
        set;
    }
}

here is logic(commented out items show failed attempts list)

//this gets all xml details except account(ACCT)
           var query1 = from item in xDoc.Descendants("ORDER")   // xDoc.Elements() //xDoc.Descendants("ORDER") // xDoc.Root.Elements("ORDER")
                        select new
                        {
                            EmpNum = item.Element("EMPNUMBER").Value,
                            ItemName = item.Element("ITEMNAME").Value,
                            OrderDate = Convert.ToDateTime(item.Element("DATETIMESTAMP").Value),

                        };


//attempt to get ACCT detail
            var Acctlist = from P in xDoc.Root.Descendants("SHIPMENTLIST")
                         select new { b = P.Element("ACCT").Value };


            foreach(var p in ACCTlist)
                ACCTgram.WriteLog("Parsed XML Acct: " + p);


//failed attempt to capture ACCT in list: 
//           List<clShipACCT> testList = ACCTlist.ToList<clShipACCT>(); 

            //////var ACCTlist = (from P in xDoc.Descendants("SHIPMENTLIST")
            //////               select new clShipACCT { strShipACCT = childitem.Element("ACCT").Value }).ToList();
            //////testShipACCTList.AddRange(ACCTlist);

Upvotes: 0

Views: 748

Answers (4)

SKG
SKG

Reputation: 152

//this works in LinqPad...Elements() return multiple instances...

void Main()
{
    XDocument doc= XDocument.Load(@"d:\test2.xml");
    var orders = doc.Root.Elements("ORDER")
        .Select (o => new Order
            {
                EmpNumber=o.Element("EMPNUMBER").Value,
                ItemName=o.Element("ITEMNAME").Value,
                TimeStamp=o.Element("DATETIMESTAMP").Value,
                Shipments=o.Element("SHIPMENTLIST").Elements("ACCT").Select (e => new Shipment{Account= e.Value}).ToList()
            }
        );

    orders.Dump();  
}



class Order
{
    public Order ()
    {
        this.Shipments=new List<Shipment>();
    }
    public string EmpNumber { get; set; }
    public string ItemName { get; set; }
    public string TimeStamp { get; set; }  //should be date time
    public string Department { get; set; }
    public List<Shipment> Shipments { get; set; }
}


class Shipment
{
    public string Account { get; set; }
}

I assumed the following xml: added ORDERS as the root element since one order in xml is really trivial...

Upvotes: 0

Fabio
Fabio

Reputation: 32455

Use .Elements method - this method return all elements with given name
.Element method will return only first element

var shipments = xDoc.Root.Descendants("SHIPMENTLIST")

List<String> acctList = new List<String>();
foreach(var accts in shipments)
{
    acctList.AddRange(accts.Elements("ACCT").Select(acct => acct.Value));
}

foreach(string acct in acctlist)
    ACCTgram.WriteLog("Parsed XML Acct: " + acct);

Upvotes: 1

Chuck Savage
Chuck Savage

Reputation: 11955

You are very close, just add your accounts search to your first query and generic object creation.

Change this to be:

var query1 = from item in xDoc.Descendants("ORDER")   // xDoc.Elements() //xDoc.Descendants("ORDER") // xDoc.Root.Elements("ORDER")
select new
{
    EmpNum = item.Element("EMPNUMBER").Value,
    ItemName = item.Element("ITEMNAME").Value,
    OrderDate = Convert.ToDateTime(item.Element("DATETIMESTAMP").Value),
    Accts = item.Element("SHIPMENTLIST").Elements("ACCT").Select(x => x.Value).ToList()
};

Upvotes: 0

Kevin
Kevin

Reputation: 1472

var result = xDoc.Root.Element("SHIPMENTLIST").Elements("ACCT").Select(x => x.Value).ToList();

Using the xml in the post, this should yield a

List<string> 

of the values in the ACCT fields.

Upvotes: 0

Related Questions