Ugrás a tartalomhoz

.NET Programming Technologies

Gergely Kovásznai, Csaba Biró

Eszterházy Károly College

Queries

Queries

All the query operators that we introduced in Section Hiba! A hivatkozási forrás nem található. can be applied to collections of XML elements and attributes in the same way as to any other collections. The only speciality is the way in which XML elements and attributes are accessed, and, furthermore, the necessity of data conversion. Let us see an instant example! We are going to load the students.xml file of the previous section, and are performing a query on the loaded data (i.e., on XElements). For instance, female students can be filtered as follows:

XElement xStudents = XElement.Load("students.xml");

var femaleStudents = from s in xStudents.Elements("student")

                                where s.Attribute("sex").Value == "female"

                                select new

                                {

                                        FirstName = s.Attribute("firstName").Value,

                                        LastName = s.Attribute("lastName").Value,

                                        DateOfBirth = new DateTime(

                                                int.Parse(s.Element("dateOfBirth").Attribute("year").Value),

                                                int.Parse(s.Element("dateOfBirth").Attribute("month").Value),

                                                int.Parse(s.Element("dateOfBirth").Attribute("day").Value)

                                        )

                                };

As can be seen, the query returns instances of an anonymous class. Instead, it would be better (more advisable and safer) to implement an own class for representing students.

As we have already claimed, all the LINQ query operators (e.g., OrderBy, GroupBy, Count etc.) can be used in the usual way on XML data as well. The next example shows how to apply one of them, the Join operator. Let us assume that, besides students’ data, we also want to include courses’ data in our application! For the sake of example, courses’ data will be loaded from another XML file (courses.xml):

<?xml version="1.0" encoding="utf-8" ?>

<courses>

        <course id="bd64f" name="Debugging" credits="3"/>

        <course id="z6df3" name="Programming Technologies" credits="3"/>

        <course id="a87d4" name="Visual Computing" credits="4"/>

        <course id="10i7e" name="Genetic Algorithms" credits="2"/>

</courses>

It is important that each course has an identifier (id attribute); we are going to use this id to access the course and to realize joins. Let us extend the content of the students.xml file with data that tells us which courses a given student is enrolled for!

<?xml version="1.0" encoding="utf-8" ?>

<students>

        <student firstName="Rita" lastName="Poratzki" sex="female">

                <dateOfBirth year="1992" month="07" day="12"/>

                <courses>

                        <course id="bd64f" grade="4"/>

                        <course id="a87d4" grade="3"/>

                </courses>

        </student>

        <student firstName="Laura" lastName="Ashley" sex="female">

                <dateOfBirth year="1993" month="01" day="09"/>

                <courses>

                        <course id="a87d4" grade="5"/>

                        <course id="z6df3" grade="2"/>

                </courses>

        </student>

        <student firstName="Steven" lastName="Drabant" sex="male">

                <dateOfBirth year="1991" month="02" day="27"/>

                <courses>

                        <course id="10i7e" grade="3"/>

                </courses>

        </student>

        ...

</students>

As can be seen, a course list appears among the data of each student, where each course is represented by its identifier (id) and the grade (grade) that the given student got on the given course.

Our query looks like as follows:

var studentsWithCourses = from s in xStudents.Elements("student")

                        select new Student

                        {

                                FirstName = ...,

                                LastName = ...,

                                Sex = ...,

                                DateOfBirth = ...,

                                Courses = from c1 in s.Element("courses").Elements("course")

                                                join c2 in xCourses.Elements("course")

                                                on c1.Attribute("id").Value equals c2.Attribute("id").Value

                                                select new CourseForStudent

                                                {

                                                        Name = c2.Attribute("name").Value,

                                                        Grade = int.Parse(c1.Attribute("grade").Value)

                                                }

                        };

As can be seen, we have defined for each student a Courses collection, in which  Name-Grade pairs are stored, where Name is the name of a course and Grade is the grade that the student got on the course. The collection is filled by a join on the student’s course list and the global course list (xCourses).

With the query result (studentsWithCourses) in hand, one can build the GUI in Figure 3.

XVI.3.  LINQ to XML – Sample application