1

I have a class that defines the xml and another class that defines the candidate and another class that it is a list of the class candidate.

I am trying to create dynamically the list according to number of nodes that I have in the xml.

I have tried all kind of variations and nothing worked, until the nodes Candidates I got all the information but the CandidateList came null all the time.

public class Candidate
{
}

public class CandidateList : List<Candidate>
{
}

public class Request
{
    public CandidateList CandidateList { get; set; }
}
<?xml version="1.0" encoding="utf-8"?>
<Requests>
  <Request>
    <MidaClientID>1040</MidaClientID>
    <!--elided other elements-->
    <OrderDescription></OrderDescription>
    <Candidates>
      <Candidate>
        <QuestNum>6</QuestNum>
        <!--elided other elements-->
        <EventNum>012</EventNum>
      </Candidate>
      <Candidate>
        <QuestNum>6</QuestNum>
         <!--elided other elements-->
        <EventNum>012</EventNum>
      </Candidate>
    </Candidates>
  </Request>
</Requests>
try
{
    IEnumerable<Request> req = from r in input.Descendants("Request")
    select new Request()
    {
        MidaClientID = (int)r.Element("MidaClientID") != 0 ? (int)r.Element("MidaClientID") : 0,
        Password = (string)r.Element("MidaClientPassword") != null ? (string)r.Element("MidaClientPassword") : string.Empty,
        ClientNum = (int)r.Element("ClientNum") != 0 ? (int)r.Element("ClientNum") : 0,
        ClientName = (string)r.Element("ClientName") != null ? (string)r.Element("ClientName") : string.Empty,
        ContactNum = (int)r.Element("ContactNum") != 0 ? (int)r.Element("ContactNum") : 0,
        ContactFirstName = (string)r.Element("ContactFirstName") != null ? (string)r.Element("ContactFirstName") : string.Empty,
        ContactLastName = (string)r.Element("ContactLastName") != null ? (string)r.Element("ContactLastName") : string.Empty,
        ContactEmail = (string)r.Element("ContactEmail") != null ? (string)r.Element("ContactEmail") : "",
        OrderID = (int)r.Element("OrderID") != 0 ? (int)r.Element("OrderID") : 0,
        OrderDesc = (string)r.Element("OrderDescription") != null ? (string)r.Element("OrderDescription") : "",
        CandidateList = (from i in input.Root.Element("Candidates").Elements("Candidate")
            select new Candidate()
            {
                QuestNum = (int)r.Element("QuestNum") != 0 ? (int)r.Element("QuestNum") : 0,
                CandNum = (int)r.Element("CandNum") != 0 ? (int)r.Element("CandNum") : 0,
                EventNum = (int)r.Element("EventNum") != 0 ? (int)r.Element("EventNum") : 0,
                EventDate = (string)(r.Element("EventDate")) == string.Empty ?
                            DateTime.Today : (DateTime)(r.Element("EventDate")),
                EventTime = (string)(r.Element("EventTime")) == string.Empty ?
                            DateTime.Now : (DateTime)(r.Element("EventTime")),
                CandFirstName = (string)r.Element("CandFirstName") != null ? (string)r.Element("CandFirstName") : string.Empty,
                CandLastName = (string)r.Element("CandLastName") != null ? (string)r.Element("CandLastName") : string.Empty,
                CandPhone1 = (string)r.Element("CandPhone1") != null ? (string)r.Element("CandPhone1") : string.Empty,
                CandPhone2 = (string)r.Element("CandPhone2") != null ? (string)r.Element("CandPhone2") : string.Empty,
                CandPhone3 = (string)r.Element("CandPhone3") != null ? (string)r.Element("CandPhone3") : string.Empty,
                CandAttach1 = (string)r.Element("CandAttach1") != null ? (string)r.Element("CandAttach1") : string.Empty,
                CandAttach2 = (string)r.Element("CandAttach2") != null ? (string)r.Element("CandAttach2") : string.Empty,
                CandAttach3 = (string)r.Element("CandAttach3") != null ? (string)r.Element("CandAttach3") : string.Empty
            }) as CandidateList
    };
    return req.ToList();
}

catch (Exception ex)
{
    throw ex;
}
Andras Zoltan
  • 41,961
  • 13
  • 104
  • 160
Danny
  • 107
  • 3
  • 13
  • I think that now it is cleaner and hope it is still clear – Danny Jul 17 '12 at 07:44
  • 1
    Suggestion on how to re-throw exceptions: [What is the proper way to re-throw an exception in C#?](http://stackoverflow.com/questions/178456/what-is-the-proper-way-to-re-throw-an-exception-in-c) – Paolo Moretti Jul 17 '12 at 08:15

2 Answers2

0

Thanks for tidying up the question - having to scroll horizontally is a bit of a nightmare (will edit to show).

Anyway - it seems that your primary problem is the bit where you select your Candidates node:

CandidateList = (from i in input.Root.Element("Candidates").Elements("Candidate") 

The problem being that the linq query does not produce a CandidateList instance. One way to do that will be to add a range constructor to your CandidateList type and feed the linq query to it. Also - I think the input.Root is wrong.

public class CandidateList : List<Candidate>{
  public CandidateList() {}
  public CandidateList(IEnumerable<Candidate> range) : base(range) {}
}
//.. in 'new Request{' block
select new Candidate {
  // ... other members elided
  CandidateList = new CandidateList(
    (from i in r.Element("Candidates").Elements("Candidate") 
    select new Candidate()     
    {   
      //...all the Candidate members
    })
  ) //<-- end of the constructor call
}

You'll also need to drop the as CandidateList from the end of that query after moving it into the constructor, otherwise you'll either get an empty CandidateList or, possibly an ArgumentNullException from the List<T> base class of CandidateList. Notice that I've change the from; since you want the Candidates/Candidate nodes for the current Requests/Request, which is given by r.

Finally - all your property assignments to the Candidate object are coming from r - you need to change those to i (the product of the inner Linq statement).

Andras Zoltan
  • 41,961
  • 13
  • 104
  • 160
  • Still getting the CandidateList as null – Danny Jul 17 '12 at 08:05
  • Changed that as you wrote and the line that refers to the elements and still null the line:from i in r.Element("Candidates").Elements("Candidate") – Danny Jul 17 '12 at 08:18
  • Now i am getting the error :Value cannot be null and the stack trace is leading me to the line : public CandidateList(IEnumerable range) : base(range){} , can you please explain the meaning of this line – Danny Jul 17 '12 at 09:05
  • It's the constructor to build a `CandidateList` from an `IEnumerable`, for which we've used your original Linq query (slightly modified) - I don't think you got rid of the `as CandidateList` from the end of your inner query - the reason I say that is because Linq queries never return `null`; only empty enumerables. You *cannot use `as CandidateList` because the linq query is not a `CandidateList`*. Indeed if you look at my answer I say that you'll get this exact problem if you leave it there :) – Andras Zoltan Jul 17 '12 at 09:10
  • First thank you for your patience, i want to learn linq very well so you are giving allot of new information, Second i am still getting the exception - Value cannot be null. Parameter name: element – Danny Jul 17 '12 at 09:25
  • CandidateList = new CandidateList((from i in r.Element("Candidates").Elements("Candidate") select new Candidate() { })) – Danny Jul 17 '12 at 09:28
  • @DannySpivak do you have any `Request`s that *don't* have a `Candidates` node? Please note - also - I've just noticed that you're also selecting from `r` on each candidate - instead of `i` – Andras Zoltan Jul 17 '12 at 10:01
  • No, for the time being i have an xml file that i am debugging with him – Danny Jul 17 '12 at 10:05
  • thank you very much everything is working excellent,and again thank you for the patience – Danny Jul 17 '12 at 10:22
0

You need to explicitly instantiate the CandidateList property.

var doc = XElement.Load(@"path-to-xml");
var result = doc.Descendants("Request")
    .Select(RequestSelector);

private Request RequestSelector(XElement elem)
{
    var request  = new Request();
    // Fill properties here
    request.Candidates = new CandidateList();
    request.Candidates.AddRange(elem.Descendants("Candidate").Select(CandidateSelector));
    return request;
}

private Candidate CandidateSelector(XElement elem)
{
    var candidate = new Candidate();
    candidate.CandFirstName = elem.Element("CandFirstName").Value;
    // Fill other properties here
    return candidate;
}
RePierre
  • 9,358
  • 2
  • 20
  • 37