I am trying to parse data from XDocument instance using Linq to XML and store it in IEnumerable<MyClass>. I do not want to get every element from the xml document, so I am using ElementAt(#index) to get the value. However sometimes the element that I want is not in the document and then I get index out of range exception. Is there a better way to parse values from this document? Here is the code:
XML Document looks like this:
<someotherelement> /* I dont want the "someotherelement" part either */
<subelement></subelement>
<subelement></subelement>
</someotherelement>
<result>
<doc>
<int name="personid">8394</int> /* I don't want this value so I am skipping it */
<str name="name">James</str>
<str name="address">30 Awesome Lane</str>
<arr name="randomearray"> /* I want to skip this too */
<str name="random1">SomeValue</str>
<str name="random2">SomeValue</str>
<str name="random2">SomeValue</str>
</arr>
<str name="city">Awesome City</str>
<str name="state">CA</str>
<int name="zipcode">84392</int>
<str name="country">USA</str>
<str name="phonenumber">8309933820</str>
<date name="reportdate">2012-07-27T06:01:05.256Z</date>
</doc>
/* This is missing address and country */
<doc>
<int name="personid">10394</int> /* I don't want this value so I am skipping it */
<str name="name">Mathew</str>
<arr name="randomearray"> /* I want to skip this too */
<str name="random1">SomeValue</str>
<str name="random2">SomeValue</str>
<str name="random2">SomeValue</str>
</arr>
<str name="city">Not Awesome City</str>
<str name="state">CA</str>
<str name="zipcode">58439</str>
<str name="phonenumber">8309933820</str>
<date name="reportdate">2012-07-27T06:01:05.256Z</date>
</doc>
</result>
Class:
public class Doc
{
public string Name {get;set;}
public string Address{get;set;}
public string City {get;set;}
public string State {get;set;}
public int ZipCode {get;set;}
public string Country {get;set;}
public string PhoneNumber {get;set;}
public DateTime ReportDate {get;set;}
}
Linq To Xml
string pathToXml = "http://www.foo.com/something";
var doc = XDocument.Load(pathToXml);
IEnumerable<Doc> myDoc = from item in doc.Descendants("doc")
select new Doc
{
Name = item.Element("str").Value,
Address = item.Element("str").ElementsAfterSelf("str").First().Value,
City = item.Element("str").ElementsAfterSelf("str").ElementAt(1).Value,
State = item.Element("str").ElementsAfterSelf("str").ElementAt(2).Value,
ZipCode = Convert.ToInt32(item.Element("int").Value)
Country = item.Element("str").ElementsAfterSelf("str").ElementAt(3).Value,
PhoneNumber = item.Element("str").ElementsAfterSelf("str").ElementAt(4).Value,
ReportDate = Convert.ToDateTime(item.Element("date").Value)
};
You may want to employ XPath which allows you to specify the elements more comfortably, using for example the values of their attributes, which seems useful in your case.
Combined with an extension method to avoid repetitive statements:
An example: