tags:

views:

51

answers:

1

Hi,

I have an XML doc like this:

<Persons>
 <Person Id="10000" FullName="Jon Doe">
  <Status StatusID="1" StatusDesc="Active"/>
      <Fields>
          <Field FieldId="1" Value="xxxx"/>
          <Field FieldId="2" Value="yyyy"/>
          <Field FieldId="2" Value="zzzz"/>
      </Fields>
 </Person>
 <Person Id="10001" FullName="John Smith">
  <Status StatusID="2" StatusDesc="New"/>
  <Fields>
      <Field FieldId="3" Value="aaaa"/>
      <Field FieldId="4" Value="bbbb"/>
     <Field FieldId="5" Value="ccccv"/>
  </Fields>
 </Person>
</Persons>

I want to write an XML query that returns the "Person" ID and all "Fields" elements. I can get all "Fields" elements but not the "Person" ID. The same applies when I need the "Status" element.

Any help will be appreciated.

+1  A: 

Try something like this:

var result = XElement.Load("Example.xml")
  .Elements("Person")
  .Select(p => new {
   Id = p.Attribute("Id").Value,
   Fields = p.Descendants("Field").Select(f => new {
      Id = f.Attribute("FieldId").Value,
      Value = f.Attribute("Value").Value
     })
  });

This will give you a sequence of anonymous types that look something like this:

class Anonymous
{
    public String Id { get; }
    public IEnumerable<AnonymousSubtype> Fields { get; }
}

class AnonymousSubtype
{
   public String Id { get; }
   public String Value { get; }
}

The reason that I used the Descendants method to retrieve the fields is because the element I am first working with is the Person element. Since Elements only returns nodes that are direct children it would not work to retrieve the fields so I used Descendants instead.

To enumerate the results you can do this:

foreach (var person in result)
{
    Console.WriteLine("Person Id: {0}", person.Id);
    foreach (var field in person.Fields)
    {
        Console.Write("  Field Id: {0}", field.Id);
        Console.WriteLine("  Field Value: {0}", field.Value);
    }
}
Andrew Hare
This is exactly what I'm looking for. I'll try it.. Thanks Andrew.
anon2010
@anon2010 - I simplified the query a bit - it is the same query just with a simplified approach.
Andrew Hare
Ty Andrew, that "let fields" statement confused me a bit. Why you used p.Descendants("Field") and not p.Elements("Field")?
anon2010
Also, how can I foreach the result??
anon2010
@anon2010 - I have updated my answer rather than commenting. To much stuff for a comment! :)
Andrew Hare
Andrew, you are my LINQ hero !!!!
anon2010
Andrew, I've tested the code last night and it works fine except when some "Person" elements has no "Field" Descendants. Then I'm getting a "null reference" error. Any ideas?
anon2010
The same happens if I call Fields = p.Descendants("Field").Select or Fields = p.Descendants("Fields").Elements("Field").Select
anon2010
@anon2010 - Can you provide a sample of the XML you have that is causing the code to throw an exception? Feel free to throw the code into the original question.
Andrew Hare