Introduction
I had a requirement as part of my assignment to convert complex XML to an object using LINQ.
The same thing using XML serialization and deserialization is available at this link.
Using the Code
We need to create the XML file in this format:
<students>
<student>
<name>Raju</name>
<batch>III</batch>
<school>School Name</school >
<marks>
<mark>
<term>I</term>
<science>46</science>
<mathematics>50</mathematics >
<language>46</language>
<result>Pass</result>
<comments>
<teacher>good</teacher>
<parent></parent>
</comments>
</mark>
<mark>
<term>II</term>
<science>47</science>
<mathematics >45</mathematics>
<language>48</language>
<result>Pass</result>
<comments>
<teacher>need to improve</teacher>
<parent>thanks</parent>
</comments>
</mark>
</marks>
</student>
</students>
Here the XML format is fairly simple – we need to convert this XML to a class object containing object array (for <marks>
node) using LINQ.
A brief explanation about this XML structure is given below.
From Top Node
- Each student has name, batch and school
- Each student has multiple term marks (example, First Term/Second Term, etc.)
- In each term, there will be separate comments about student performance (teacher/parent)
How do we convert this as an object?
It is really simple ... we start from the bottom i.e., <comments>
.
Step I: Convert <comments>
as class:
<comments>
<teacher>need to improve</teacher>
<parent>thanks.</parent>
</comments>
public class Comment
{
private string _teacherComment;
private string _parentComment;
public string TeacherComment
{
get { return _teacherComment; }
set { _teacherComment = value; }
}
public string ParentComment
{
get { return _parentComment; }
set { _parentComment = value; }
}
}
Step II: Convert <mark>
as class:
<mark>
<term>I</term>
<science>46</science>
<mathematics>50</mathematics >
<language>46</language>
<result>Pass</result>
<comments>
<teacher>good</teacher>
<parent></parent>
</comments>
</mark>
public class Mark
{
private string _term;
private string _science;
private string _mathematics;
private string _language;
private string _result;
public string Term
{
get { return _term; }
set { _term = value; }
}
public string Science { get / set }
…
…
public string Result { get / set }
public Comment objComment = new Comment();
}
Here we added Comment
within Mark
class -i.e.,
public Comment objComment = new Comment();
As I mentioned at the top, a student can have multiple marks based on the term/session. so we need to create List <T>
of marks as below:
List<Mark> objMarkList = new List<Mark>();
Step III: Create a class for <student>
:
public class Student
{
private string _studentName;
private string _batch;
private string _school;
public string StudentName
{ get { return _studentName; } set { _studentName = value; } }
public string Batch
{ get { return _batch; } set { _batch = value; } }
public string School
{ get { return _school; } set { _school = value; } }
public List<Mark> objMarkList = new List<Mark>();
}
We have created a Student
class with Mark
which contains Comment
.
Let’s move to LINQ
XDocument xdoc1 = XDocument.Load("your xml Path");
Student objStudent = new Student();
List<Student> lstStudent
= (from _student in xdoc1.Element("students").Elements("student")
select new Student
{
StudentName = _student.Element("name").Value,
Batch = _student.Element("batch").Value,
School = _student.Element("school").Value,
objMarkList = (from _marks in _student.Element("marks").Elements("mark")
select new Mark
{
Term = _marks.Element("term").Value,
Science = _marks.Element("science").Value,
Mathematics = _marks.Element("mathematics").Value,
Language = _marks.Element("language").Value,
Result = _marks.Element("result").Value,
objComment = (from _cmt in _marks.Elements("comments")
select new Comment
{
TeacherComment = _cmt.Element("teacher").Value,
ParentComment = _cmt.Element("parent").Value
}).FirstOrDefault(),
}).ToList()
}).ToList();
foreach (var _stud in lstStudent)
{
}