Every programmer has had to parse an XML file. If you're trying to tell me you haven't, then you're lying and you just don't remember it. You probably shouldn't even call yourself a programmer.
If you don't remember the history of reading an XML document, here's the Cliffs Notes version. In the beginning there was line-by-line parsing. It was hard, error prone, and usually sucked. After a little while of this, light started shining onto our dark corner of the world. .NET introduced the XmlTextReader class, and things were good - for a while. And then, as if Microsoft heard the prayers of a million programmers, LINQ was integrated into .NET 3.5 and again, things are good.
It's the anonymous types and methods introduced into .NET 3.5 that makes LINQ possible. If you haven't messed with anonymous types yet, I would highly recommend it. MSDN has some good documentation.
Let's start out this tutorial by looking at some XML code. I've created a small document that outlines some of the tutorials we've created.
<Tutorials>
<Tutorial>
<Author>The Reddest</Author>
<Title>
Creating an XP Style WPF Button with Silverlight
</Title>
<Date>2/20/2008</Date>
</Tutorial>
<Tutorial>
<Author>The Fattest</Author>
<Title>
Flex And Yahoo Maps
</Title>
<Date>2/12/2007</Date>
</Tutorial>
<Tutorial>
<Author>The Tallest</Author>
<Title>
WPF Tutorial - Creating A Custom Panel Control
</Title>
<Date>2/18/2008</Date>
</Tutorial>
</Tutorials>
First, we're going to use some simple LINQ syntax to create some anonymous objects with the properties, Author, Title, and Date.
var tutorials = from tutorial in xmlDoc.Descendants("Tutorial")
select new
{
Author = tutorial.Element("Author").Value,
Title = tutorial.Element("Title").Value,
Date = tutorial.Element("Date").Value,
};
The result of this code will be an IEnumerable collection filled with anonymous objects. What's nice about Visual Studio is that you'll even get dot completion for anonymous types.
Anonymous objects are well and good, but usually I want something a little better defined to pass around my application. Let's look at how to create a List of Tutorial objects.
{
public string Author { get; set; }
public string Title { get; set; }
public DateTime Date { get; set; }
}
...
List<Tutorial> tutorials =
(from tutorial in xmlDoc.Descendants("Tutorial")
select new Tutorial
{
Author = tutorial.Element("Author").Value,
Title = tutorial.Element("Title").Value,
Date = DateTime.Parse(tutorial.Element("Date").Value),
}).ToList<Tutorial>();
At this point, you're probably floored at how quickly I was just able to parse that XML document into my collection - I know I am. Let's look at one simple piece I haven't mentioned yet, the where clause. Just like SQL, LINQ has the ability to filter results using the where keyword. Let's filter down my collection to only tutorials written by The Tallest (his are always the best anyway).
(from tutorial in xmlDoc.Descendants("Tutorial")
where tutorial.Element("Author").Value == "The Tallest"
select new Tutorial
{
Author = tutorial.Element("Author").Value,
Title = tutorial.Element("Title").Value,
Date = DateTime.Parse(tutorial.Element("Date").Value),
}).ToList<Tutorial>();
Now my list of tutorials will only contain those written by The Tallest.
I think that's enough for the first part of this tutorial. LINQ is incredibly powerful and deserves several tutorials to cover even a small portion of it. LINQ can be used for databases just as easily as it was used here on XML. You can even write an entire ray tracer, if you're deranged enough.
03/06/2008 - 20:02
Really nice info. I've got to check deeply this whole new addition named LINQ. It seems truly powerful.
Thanks for the post.
05/27/2008 - 00:02
Its really cool and very easy to understand tutorial.
So simple that a novice can start up just going through ur tutorial.
hope for few more in future
take care
08/06/2008 - 03:18
Data Source=xxx.xxx.xxx.xxx,1433;" & _
"Initial Catalog=mySQLServerDBName;" & _
"User ID=myUsername;" & _
"Password=myPassword"
08/14/2008 - 08:42
From Argentine.. Thanks! great article!
10/15/2008 - 19:04
Really good tutorial. It saved lot of my time
10/25/2008 - 08:31
Truely simple and very helpful article.
It helped me to start up with xlinq very quickly.
Thanks for this. :)..
06/10/2009 - 11:00
Very well done, I appreciate the help.
02/02/2010 - 23:32
This is the shortest and well explained first-step tutorial for LINQ I have ever seen.
Thank you!
02/10/2010 - 09:33
Thanks for the good article. I like LINQ very much and am trying to use it whenever possible. My one concern is the performance. Do you know how LINQ performs compared with the traditional approach? For example, your example xml could be loaded through xml serialization. How does it perform compared with the LINQ?
04/28/2010 - 13:42
Thanks for wonderful tutorial.
Good job
12/09/2010 - 17:11
This example is AMAZING! Exactly what I needed. Thank you so much :)
12/18/2010 - 01:09
very helpful...
03/09/2011 - 20:07
I like it. You saved me a lot of time. Thanks!
03/29/2011 - 11:43
This is great but what do you do when you don't know the structure of the xml when you write the code? Linq doesn't work in this case. Back to parsing it line by line, character by character.
04/12/2011 - 07:31
hallo all
could any body help me to read this xml with using VS08 I need to creat a sample code :
<sdma:OperationExtension xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sdma="http://ns.storydriven.org/sdm/activities/0.1.0" xmlns:sdme="http://ns.storydriven.org/sdm/expressions/0.1.0" xmlns:sdmp="http://ns.storydriven.org/sdm/patterns/0.1.0" xmlns:sdmpe="http://ns.storydriven.org/sdm/patterns/expressions/0.1.0" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xsi:schemaLocation="http://ns.storydriven.org/sdm/activities/0.1.0 http://ns.storydriven.org/sdm/0.1.0#//activities http://ns.storydriven.org/sdm/expressions/0.1.0 http://ns.storydriven.org/sdm/0.1.0#//expressions http://ns.storydriven.org/sdm/patterns/0.1.0 http://ns.storydriven.org/sdm/0.1.0#//patterns http://ns.storydriven.org/sdm/patterns/expressions/0.1.0 http://ns.storydriven.org/sdm/0.1.0#//patterns/expressions">
<ownedActivity>
<!-- 0 -->
<ownedActivityNode xsi:type="sdma:StopNode" incoming="#//@ownedActivity/@ownedActivityEdge.5 #//@ownedActivity/@ownedActivityEdge.0" name="stopWrongAnswer">
<returnValue xsi:type="sdme:TextualExpression" expressionText="false" />
</ownedActivityNode>
<!-- 1 -->
<ownedActivityNode xsi:type="sdma:StopNode" incoming="#//@ownedActivity/@ownedActivityEdge.1 #//@ownedActivity/@ownedActivityEdge.8" name="stopRightAnswer">
<returnValue xsi:type="sdme:TextualExpression" expressionText="true" />
</ownedActivityNode>
<!-- 2 -->
<ownedActivityNode xsi:type="sdma:ModifyingStoryNode" incoming="#//@ownedActivity/@ownedActivityEdge.4" outgoing="#//@ownedActivity/@ownedActivityEdge.0" name="wrongAnswerPenalizeCard">
<ownedRule>
<objectVariable name="previousPartition" classifier="http://www.moflon.org/MemoryBoxLanguage#//Partition" incomingLink="#//@ownedActivity/@ownedActivityNode.2/@ownedRule/@linkVariable.1 #//@ownedActivity/@ownedActivityNode.2/@ownedRule/@linkVariable.2" bindingState="BOUND" />
<objectVariable name="card" classifier="http://www.moflon.org/MemoryBoxLanguage#//Card" outgoingLink="#//@ownedActivity/@ownedActivityNode.2/@ownedRule/@linkVariable.0 #//@ownedActivity/@ownedActivityNode.2/@ownedRule/@linkVariable.1" bindingState="BOUND" />
<objectVariable name="this" classifier="http://www.moflon.org/MemoryBoxLanguage#//Partition" incomingLink="#//@ownedActivity/@ownedActivityNode.2/@ownedRule/@linkVariable.0" outgoingLink="#//@ownedActivity/@ownedActivityNode.2/@ownedRule/@linkVariable.2" bindingState="BOUND" />
<linkVariable xsi:type="sdmp:LinkVariable" name="cardContainer" modifier="DESTROY" target="#//@ownedActivity/@ownedActivityNode.2/@ownedRule/@objectVariable.1" source="#//@ownedActivity/@ownedActivityNode.2/@ownedRule/@objectVariable.2" />
<linkVariable xsi:type="sdmp:LinkVariable" name="cardContainer" modifier="CREATE" target="#//@ownedActivity/@ownedActivityNode.2/@ownedRule/@objectVariable.1" source="#//@ownedActivity/@ownedActivityNode.2/@ownedRule/@objectVariable.0" />
<linkVariable xsi:type="sdmp:LinkVariable" name="previous" source="#//@ownedActivity/@ownedActivityNode.2/@ownedRule/@objectVariable.2" target="#//@ownedActivity/@ownedActivityNode.2/@ownedRule/@objectVariable.0" />
</ownedRule>
</ownedActivityNode>
<!-- 3 -->
<ownedActivityNode xsi:type="sdma:ModifyingStoryNode" incoming="#//@ownedActivity/@ownedActivityEdge.7" outgoing="#//@ownedActivity/@ownedActivityEdge.1" name="rightAnswerPromoteCard">
<ownedRule>
<objectVariable name="nextPartition" classifier="http://www.moflon.org/MemoryBoxLanguage#//Partition" incomingLink="#//@ownedActivity/@ownedActivityNode.3/@ownedRule/@linkVariable.2" outgoingLink="#//@ownedActivity/@ownedActivityNode.3/@ownedRule/@linkVariable.0" bindingState="BOUND" />
<objectVariable name="this" classifier="http://www.moflon.org/MemoryBoxLanguage#//Partition" incomingLink="#//@ownedActivity/@ownedActivityNode.3/@ownedRule/@linkVariable.1 #//@ownedActivity/@ownedActivityNode.3/@ownedRule/@linkVariable.0" bindingState="BOUND" />
<objectVariable name="card" classifier="http://www.moflon.org/MemoryBoxLanguage#//Card" outgoingLink="#//@ownedActivity/@ownedActivityNode.3/@ownedRule/@linkVariable.1 #//@ownedActivity/@ownedActivityNode.3/@ownedRule/@linkVariable.2" bindingState="BOUND" />
<linkVariable xsi:type="sdmp:LinkVariable" name="previous" source="#//@ownedActivity/@ownedActivityNode.3/@ownedRule/@objectVariable.0" target="#//@ownedActivity/@ownedActivityNode.3/@ownedRule/@objectVariable.1" />
<linkVariable xsi:type="sdmp:LinkVariable" name="cardContainer" modifier="DESTROY" target="#//@ownedActivity/@ownedActivityNode.3/@ownedRule/@objectVariable.2" source="#//@ownedActivity/@ownedActivityNode.3/@ownedRule/@objectVariable.1" />
<linkVariable xsi:type="sdmp:LinkVariable" name="cardContainer" modifier="CREATE" target="#//@ownedActivity/@ownedActivityNode.3/@ownedRule/@objectVariable.2" source="#//@ownedActivity/@ownedActivityNode.3/@ownedRule/@objectVariable.0" />
</ownedRule>
</ownedActivityNode>
<!-- 4 -->
<ownedActivityNode xsi:type="sdma:ModifyingStoryNode" incoming="#//@ownedActivity/@ownedActivityEdge.6" outgoing="#//@ownedActivity/@ownedActivityEdge.2 #//@ownedActivity/@ownedActivityEdge.3" name="isGuessCorrect">
<ownedRule>
<objectVariable name="card" classifier="http://www.moflon.org/MemoryBoxLanguage#//Card" bindingState="BOUND">
<constraint>
<constraintExpression xsi:type="sdme:ComparisonExpression" operator="EQUAL">
<leftExpression xsi:type="sdmpe:AttributeValueExpression" object="#//@ownedActivity/@ownedActivityNode.4/@ownedRule/@objectVariable.0" attribute="http://www.moflon.org/MemoryBoxLanguage#//Card/back" />
<rightExpression xsi:type="sdme:LiteralExpression" comment="" value="guessed" valueType="ecore:EString" />
</constraintExpression>
</constraint>
</objectVariable>
</ownedRule>
</ownedActivityNode>
<!-- 5 -->
<ownedActivityNode xsi:type="sdma:ModifyingStoryNode" incoming="#//@ownedActivity/@ownedActivityEdge.3" outgoing="#//@ownedActivity/@ownedActivityEdge.4 #//@ownedActivity/@ownedActivityEdge.5" name="canCardBePenalized">
<ownedRule>
<objectVariable name="this" classifier="http://www.moflon.org/MemoryBoxLanguage#//Partition" outgoingLink="#//@ownedActivity/@ownedActivityNode.5/@ownedRule/@linkVariable.0" bindingState="BOUND" />
<objectVariable name="previousPartition" classifier="http://www.moflon.org/MemoryBoxLanguage#//Partition" incomingLink="#//@ownedActivity/@ownedActivityNode.5/@ownedRule/@linkVariable.0" />
<linkVariable xsi:type="sdmp:LinkVariable" name="previous" source="#//@ownedActivity/@ownedActivityNode.5/@ownedRule/@objectVariable.0" target="#//@ownedActivity/@ownedActivityNode.5/@ownedRule/@objectVariable.1" />
</ownedRule>
</ownedActivityNode>
<!-- 6 -->
<ownedActivityNode xsi:type="sdma:StartNode" name="Partition::check (card: Card, guessed: EString): EBoolean" outgoing="#//@ownedActivity/@ownedActivityEdge.6" />
<!-- 7 -->
<ownedActivityNode xsi:type="sdma:ModifyingStoryNode" incoming="#//@ownedActivity/@ownedActivityEdge.2" outgoing="#//@ownedActivity/@ownedActivityEdge.7 #//@ownedActivity/@ownedActivityEdge.8" name="canCardBePromoted">
<ownedRule>
<objectVariable name="nextPartition" classifier="http://www.moflon.org/MemoryBoxLanguage#//Partition" outgoingLink="#//@ownedActivity/@ownedActivityNode.7/@ownedRule/@linkVariable.0" />
<objectVariable name="this" classifier="http://www.moflon.org/MemoryBoxLanguage#//Partition" incomingLink="#//@ownedActivity/@ownedActivityNode.7/@ownedRule/@linkVariable.0" bindingState="BOUND" />
<linkVariable xsi:type="sdmp:LinkVariable" name="previous" source="#//@ownedActivity/@ownedActivityNode.7/@ownedRule/@objectVariable.0" target="#//@ownedActivity/@ownedActivityNode.7/@ownedRule/@objectVariable.1" />
</ownedRule>
</ownedActivityNode>
<ownedActivityEdge target="#//@ownedActivity/@ownedActivityNode.0" source="#//@ownedActivity/@ownedActivityNode.2" />
<ownedActivityEdge target="#//@ownedActivity/@ownedActivityNode.1" source="#//@ownedActivity/@ownedActivityNode.3" />
<ownedActivityEdge target="#//@ownedActivity/@ownedActivityNode.7" source="#//@ownedActivity/@ownedActivityNode.4" guardType="SUCCESS" />
<ownedActivityEdge target="#//@ownedActivity/@ownedActivityNode.5" source="#//@ownedActivity/@ownedActivityNode.4" guardType="FAILURE" />
<ownedActivityEdge target="#//@ownedActivity/@ownedActivityNode.2" source="#//@ownedActivity/@ownedActivityNode.5" guardType="SUCCESS" />
<ownedActivityEdge target="#//@ownedActivity/@ownedActivityNode.0" source="#//@ownedActivity/@ownedActivityNode.5" guardType="FAILURE" />
<ownedActivityEdge target="#//@ownedActivity/@ownedActivityNode.4" source="#//@ownedActivity/@ownedActivityNode.6" />
<ownedActivityEdge target="#//@ownedActivity/@ownedActivityNode.3" source="#//@ownedActivity/@ownedActivityNode.7" guardType="SUCCESS" />
<ownedActivityEdge target="#//@ownedActivity/@ownedActivityNode.1" source="#//@ownedActivity/@ownedActivityNode.7" guardType="FAILURE" />
</ownedActivity>
</sdma:OperationExtension>
thats it .
I waiting for ur helpniss, thanxxx
09/09/2011 - 05:54
gar mereche.ei code ekhon k ghatbe..!!
11/10/2011 - 05:38
This is very helpful for me and you saved me a lot of time.
Thanks for wonderful tutorial.
01/20/2012 - 03:56
Good one
Add Comment
[language] [/language]
Examples:
[javascript] [/javascript]
[actionscript] [/actionscript]
[csharp] [/csharp]
See here for supported languages.
Javascript must be enabled to submit anonymous comments - or you can login.