Siêu thị PDFTải ngay đi em, trời tối mất

Thư viện tri thức trực tuyến

Kho tài liệu với 50,000+ tài liệu học thuật

© 2023 Siêu thị PDF - Kho tài liệu học thuật hàng đầu Việt Nam

Apress pro LINQ Language Integrated Query in C# 2008 phần 6 ppt
PREMIUM
Số trang
52
Kích thước
822.2 KB
Định dạng
PDF
Lượt xem
1395

Apress pro LINQ Language Integrated Query in C# 2008 phần 6 ppt

Nội dung xem thử

Mô tả chi tiết

CHAPTER 8 ■ LINQ TO XML OPERATORS 275

new XElement("BookParticipant",

new XAttribute("type", "Editor"),

new XElement("FirstName", "Ewan"),

new XElement("LastName", "Buckingham"))));

IEnumerable<XElement> elements =

xDocument.Element("BookParticipants").Descendants("FirstName");

// First, I will display the source elements.

foreach (XElement element in elements)

{

Console.WriteLine("Source element: {0} : value = {1}",

element.Name, element.Value);

}

// Now, I will display the ancestor elements for each source element.

foreach (XElement element in elements.Ancestors())

{

Console.WriteLine("Ancestor element: {0}", element.Name);

}

In the previous example, first, I create an XML document. Next, I generate a sequence of FirstName

elements. Remember, this Ancestors method is called on a sequence of nodes, not on a single node,

so I need a sequence on which to call it. Because I want to be able to display the names of the nodes

for identification purposes, I actually build a sequence of elements because elements have names

but nodes do not. I then enumerate through the sequence displaying the source elements just so you

can see the source sequence. Then, I enumerate on the elements returned from the Ancestors method

and display them. Here are the results:

Source element: FirstName : value = Joe

Source element: FirstName : value = Ewan

Ancestor element: BookParticipant

Ancestor element: BookParticipants

Ancestor element: BookParticipant

Ancestor element: BookParticipants

As you can see, it displays the two source sequence elements, the two FirstName elements. It

then displays the ancestors for each of those two elements.

So using the Ancestors operator, I am able to retrieve all of the ancestor elements for each

node in a sequence of nodes. In this case, my sequence is a sequence of elements, but that is alright

because an element is derived from a node. Remember, do not confuse the Ancestors operator

that is called on a sequence of nodes, which I just demonstrated, with the Ancestors method I

cover in the previous chapter.

Now this example is not quite as impressive as it could be because I needed to expand the code

for demonstration purposes. For example, I wanted to capture the sequence of FirstName elements,

because I wanted to display them so you could see the source elements in the output. So the state￾ment containing the call to the Descendants method and the subsequent foreach block are for this

purpose. Then in the second foreach loop, I call the Ancestors operator and display each ancestor

element. In reality, in that second foreach loop, I could have called the Ancestors method from the

previous chapter on each element in the sequence of FirstName elements and not even called the

Ancestors operator I am demonstrating. Listing 8-2 is an example demonstrating what I could have

done, which would have accomplished the same result, but without even using the Ancestors operator.

Rattz_789-3.book Page 275 Tuesday, October 16, 2007 2:21 PM

276 CHAPTER 8 ■ LINQ TO XML OPERATORS

Listing 8-2. The Same Results as Listing 8-1 But Without Calling the Ancestors Operator

XDocument xDocument = new XDocument(

new XElement("BookParticipants",

new XElement("BookParticipant",

new XAttribute("type", "Author"),

new XElement("FirstName", "Joe"),

new XElement("LastName", "Rattz")),

new XElement("BookParticipant",

new XAttribute("type", "Editor"),

new XElement("FirstName", "Ewan"),

new XElement("LastName", "Buckingham"))));

IEnumerable<XElement> elements =

xDocument.Element("BookParticipants").Descendants("FirstName");

// First, I will display the source elements.

foreach (XElement element in elements)

{

Console.WriteLine("Source element: {0} : value = {1}",

element.Name, element.Value);

}

foreach (XElement element in elements)

{

// Call the Ancestors method on each element.

foreach(XElement e in element.Ancestors())

// Now, I will display the ancestor elements for each source element.

Console.WriteLine("Ancestor element: {0}", e.Name);

}

The difference between this example and the previous is that instead of calling the Ancestors

operator on the elements sequence in the foreach loop, I just loop on each element in the sequence

and call the Ancestors method on it. In this example, I never call the Ancestors operator; I merely call

the Ancestors method from the previous chapter. This code produces the same output though:

Source element: FirstName : value = Joe

Source element: FirstName : value = Ewan

Ancestor element: BookParticipant

Ancestor element: BookParticipants

Ancestor element: BookParticipant

Ancestor element: BookParticipants

However, thanks to the Ancestors operator and the conciseness of LINQ, this query can be

combined into a single, more concise statement as demonstrated in Listing 8-3.

Listing 8-3. A More Concise Example of Calling the First Ancestors Prototype

XDocument xDocument = new XDocument(

new XElement("BookParticipants",

new XElement("BookParticipant",

new XAttribute("type", "Author"),

new XElement("FirstName", "Joe"),

new XElement("LastName", "Rattz")),

Rattz_789-3.book Page 276 Tuesday, October 16, 2007 2:21 PM

CHAPTER 8 ■ LINQ TO XML OPERATORS 277

new XElement("BookParticipant",

new XAttribute("type", "Editor"),

new XElement("FirstName", "Ewan"),

new XElement("LastName", "Buckingham"))));

foreach (XElement element in

xDocument.Element("BookParticipants").Descendants("FirstName").Ancestors())

{

Console.WriteLine("Ancestor element: {0}", element.Name);

}

In this example, I cut right to the chase and call the Ancestors operator on the sequence of elements

returned by the Descendants method. So the Descendants method returns a sequence of elements,

and the Ancestors operator will return a sequence of elements containing all ancestors of every

element in the sequence it is called on.

Since this code is meant to be more concise, it does not display the FirstName elements as the

two previous examples did. However, the ancestor elements should be the same. Let’s verify that

they are:

Ancestor element: BookParticipant

Ancestor element: BookParticipants

Ancestor element: BookParticipant

Ancestor element: BookParticipants

And they are! In your production code, you would probably opt for a more concise query like the

one I just presented. However, in this chapter, the examples will be more verbose, like Listing 8-1, for

demonstration purposes.

To demonstrate the second Ancestors prototype, I will use the same basic code as Listing 8-1,

except I will change the call to the Ancestors operator so that it includes the parameter BookParticipant

so that I only get the elements matching that name. That code looks like Listing 8-4.

Listing 8-4. Calling the Second Ancestors Prototype

XDocument xDocument = new XDocument(

new XElement("BookParticipants",

new XElement("BookParticipant",

new XAttribute("type", "Author"),

new XElement("FirstName", "Joe"),

new XElement("LastName", "Rattz")),

new XElement("BookParticipant",

new XAttribute("type", "Editor"),

new XElement("FirstName", "Ewan"),

new XElement("LastName", "Buckingham"))));

IEnumerable<XElement> elements =

xDocument.Element("BookParticipants").Descendants("FirstName");

// First, I will display the source elements.

foreach (XElement element in elements)

{

Console.WriteLine("Source element: {0} : value = {1}",

element.Name, element.Value);

}

Rattz_789-3.book Page 277 Tuesday, October 16, 2007 2:21 PM

278 CHAPTER 8 ■ LINQ TO XML OPERATORS

// Now, I will display the ancestor elements for each source element.

foreach (XElement element in elements.Ancestors("BookParticipant"))

{

Console.WriteLine("Ancestor element: {0}", element.Name);

}

The results now should only include the BookParticipant elements and of course the source

elements, but the two BookParticipants elements that are displayed in the first prototype’s example

should now be gone:

Source element: FirstName : value = Joe

Source element: FirstName : value = Ewan

Ancestor element: BookParticipant

Ancestor element: BookParticipant

And they are.

AncestorsAndSelf

The AncestorsAndSelf operator can be called on a sequence of elements and returns a sequence

containing the ancestor elements of each source element and the source element itself. This operator is

just like the Ancestors operator except for the fact that it can only be called on elements, as opposed

to nodes, and also includes each source element in the returned sequence of ancestor elements.

Prototypes

The AncestorsAndSelf operator has two prototypes.

The First AncestorsAndSelf Prototype

public static IEnumerable<XElement> AncestorsAndSelf (

this IEnumerable<XElement> source

)

This version of the operator can be called on a sequence of elements and returns a sequence of

elements containing each source element itself and its ancestor elements.

The Second AncestorsAndSelf Prototype

public static IEnumerable<XElement> AncestorsAndSelf<T> (

this IEnumerable<XElement> source,

XName name

)

This version is like the first, except a name is passed and only those source elements and its

ancestors matching the specified name are returned in the output sequence.

Examples

For an example of the first AncestorsAndSelf prototype, I will use the same basic example I used for

the first Ancestors prototype, except I will call the AncestorsAndSelf operator instead of the Ancestors

operator, as shown in Listing 8-5.

Rattz_789-3.book Page 278 Tuesday, October 16, 2007 2:21 PM

CHAPTER 8 ■ LINQ TO XML OPERATORS 279

Listing 8-5. Calling the First AncestorsAndSelf Prototype

XDocument xDocument = new XDocument(

new XElement("BookParticipants",

new XElement("BookParticipant",

new XAttribute("type", "Author"),

new XElement("FirstName", "Joe"),

new XElement("LastName", "Rattz")),

new XElement("BookParticipant",

new XAttribute("type", "Editor"),

new XElement("FirstName", "Ewan"),

new XElement("LastName", "Buckingham"))));

IEnumerable<XElement> elements =

xDocument.Element("BookParticipants").Descendants("FirstName");

// First, I will display the source elements.

foreach (XElement element in elements)

{

Console.WriteLine("Source element: {0} : value = {1}",

element.Name, element.Value);

}

// Now, I will display the ancestor elements for each source element.

foreach (XElement element in elements.AncestorsAndSelf())

{

Console.WriteLine("Ancestor element: {0}", element.Name);

}

Just as with the first Ancestors prototype, first, I create an XML document. Next, I generate a

sequence of FirstName elements. Remember, this AncestorsAndSelf method is called on a sequence

of elements, not on a single element, so I need a sequence on which to call it. I then enumerate through

the sequence displaying the source elements just so you can see the source sequence. Then, I enumerate

on the elements returned from the AncestorsAndSelf method and display them.

If this works as I expect, the results should be the same as the results from the first Ancestors

prototype’s example, except now the FirstName elements should be included in the output. Here are

the results:

Source element: FirstName : value = Joe

Source element: FirstName : value = Ewan

Ancestor element: FirstName

Ancestor element: BookParticipant

Ancestor element: BookParticipants

Ancestor element: FirstName

Ancestor element: BookParticipant

Ancestor element: BookParticipants

For an example of the second AncestorsAndSelf prototype, I will use the same basic example

that I used in the example for the second Ancestors prototype, except, of course, I will change the call

from the Ancestors method to the AncestorsAndSelf method, as shown in Listing 8-6.

Rattz_789-3.book Page 279 Tuesday, October 16, 2007 2:21 PM

Tải ngay đi em, còn do dự, trời tối mất!