13.07.2015 Views

C# in Depth

C# in Depth

C# in Depth

SHOW MORE
SHOW LESS
  • No tags were found...

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

342 CHAPTER 12 LINQ beyond collectionsmany different th<strong>in</strong>gs that an XElement could iterate through. XElement conta<strong>in</strong>s anumber of axis methods that are used as query sources. If you’re familiar with XPath,the idea of an axis will no doubt be familiar to you. Here are the axis methods useddirectly for query<strong>in</strong>g, each of which returns an appropriate IEnumerable:■ Ancestors ■ DescendantNodes■ AncestorsAndSelf ■ DescendantNodesAndSelf■ Annotations ■ Elements■ Attributes ■ ElementsAfterSelf■ Descendants ■ ElementsBeforeSelf■ DescendantsAndSelfAll of these are fairly self-explanatory (and the MSDN documentation provides moredetails). There are useful overloads to retrieve only nodes with an appropriate name:call<strong>in</strong>g Descendants("user") on an XElement will return all user elements underneaththe element you call it on, for <strong>in</strong>stance. A number of extension methods alsomake these axes available to whole sequences of nodes: the result is a concatenatedsequence as if the method has been called on each node <strong>in</strong> turn.As well as these calls return<strong>in</strong>g sequences, there are some methods that return as<strong>in</strong>gle result—Attribute and Element are the most important, return<strong>in</strong>g the namedattribute and the first descendant element with the specified name, respectively.One aspect of XAttribute that is particularly relevant to query<strong>in</strong>g is the set of theexplicit conversions from an XAttribute to any number of other types, such as <strong>in</strong>t,str<strong>in</strong>g, and DateTime. These are important for both filter<strong>in</strong>g and project<strong>in</strong>g results.Enough talk! Let’s see some code. We’ll start off simply, just display<strong>in</strong>g the userswith<strong>in</strong> our XML structure, as shown <strong>in</strong> list<strong>in</strong>g 12.17.List<strong>in</strong>g 12.17Display<strong>in</strong>g the users with<strong>in</strong> an XML structureXElement root = XmlSampleData.GetElement();var query = from user <strong>in</strong> root.Element("users").Elements()select new { Name=(str<strong>in</strong>g)user.Attribute("name"),UserType=(str<strong>in</strong>g)user.Attribute("type") };foreach (var user <strong>in</strong> query){Console.WriteL<strong>in</strong>e ("{0}: {1}", user.Name, user.UserType);}After creat<strong>in</strong>g the data at the start, we navigate down to the users element, and ask itfor its direct child elements. This two-step fetch could be shortened to justroot.Descendants("user"), but it’s good to see the more rigid navigation so youcan use it where necessary. It’s also more robust <strong>in</strong> the face of changes to the documentstructure, such as another (unrelated) user element be<strong>in</strong>g added elsewhere <strong>in</strong>the document.The rest of the query expression is merely a projection of an XElement <strong>in</strong>to ananonymous type. I’ll admit that we’re cheat<strong>in</strong>g slightly with the user type: we’ve kept itas a str<strong>in</strong>g <strong>in</strong>stead of call<strong>in</strong>g Enum.Parse to convert it <strong>in</strong>to a proper UserType value.The latter approach works perfectly well—but it’s quite longw<strong>in</strong>ded when you onlyLicensed to Rhona Hadida

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!