LINQ SelectMany Method
When objects contain properties which hold a collection of objects, using the Select method is not applicable…
If you played with the XML Document Object Model classes to create XML documents from scratch, it will be easy for you to migrate to a brand new set of classes which allows you to create XML elements in a much more natural and easier way. These classes are located inside the Sytem.Linq.Xml namespace. The classic way of loading an XML document is by using the XmlDocument class from the System.Xml namespace.
XmlDocument doc = XmlDocument.Load("myXmlFile.xml");
There is no difference if you are going to use the newer XDocument class.
XDocument doc = XDocument.Load("myXmlFile.xml");
So what makes this new classes have besides from having shorter names compared to their older versions? The answer is functional construction. With functional construction, you don’t need to declare the XML DOM elements one by one. You can simply use the overloaded constructors of each X class to suit your needs. This can be seen clearer by looking at an example.
By using the old System.Xml‘s XML DOM classes, the following code is used to create a simple XML file.
//A new XML Document XmlDocument doc = new XmlDocument(); //Xml Declaration XmlDeclaration declaration = doc.CreateXmlDeclaration("1.0", "utf-8", "yes"); //Attach declaration to the document doc.AppendChild(declaration); //Create a comment XmlComment comment = doc.CreateComment("This is a comment"); //Attach comment to the document doc.AppendChild(comment); //Create root element XmlElement root = doc.CreateElement("Persons"); //Attach the root node to the document doc.AppendChild(root); //Create a Person child element XmlElement person1 = doc.CreateElement("Person"); //Add an attribute name with value John Smith person1.SetAttribute("name", "John Smith"); //Crate Age element XmlElement person1Age = doc.CreateElement("Age"); person1Age.InnerText = "30"; //Create Gender element XmlElement person1Gender = doc.CreateElement("Gender"); person1Gender.InnerText = "Male"; //Attach Age and Gender element to the Person element person1.AppendChild(person1Age); person1.AppendChild(person1Gender); //Attach Person child element to the root Persons element doc.DocumentElement.AppendChild(person1); //Create another Person child element XmlElement person2 = doc.CreateElement("Person"); //Add attribute name with value Mike Folley person2.SetAttribute("name", "Mike Folley"); //Crate Age element XmlElement person2Age = doc.CreateElement("Age"); person2Age.InnerText = "25"; //Create Gender element XmlElement person2Gender = doc.CreateElement("Gender"); person2Gender.InnerText = "Male"; //Attach Age and Gender element to the Person element person2.AppendChild(person2Age); person2.AppendChild(person2Gender); //Attach second Person child element to the root Persons element doc.DocumentElement.AppendChild(person2); //Save the constructed XML into an XML file doc.Save(@"C:\sample1.xml");
Example 1 – Using XML DOM classes to create a file
The above code will produce the followingXML:
<?xml version="1.0" encoding="utf-8" standalone="yes"?> <!--This is a comment--> <Persons> <Person name="John Smith"> <Age>30</Age> <Gender>Male</Gender> </Person> <Person name="Mike Folley"> <Age>25</Age> <Gender>Male</Gender> </Person> </Persons>
Now let’s take a look at using the new LINQ to XML classes to create the very same XML markup.
XDocument doc = new XDocument( new XDeclaration("1.0", "utf-8", "yes"), new XComment("This is a comment"), new XElement("Persons", new XElement("Person", new XAttribute("name", "John Smith"), new XElement("Age", new XText("30")), new XElement("Gender", new XText("Male"))), new XElement("Person", new XAttribute("name", "Mike Folley"), new XElement("Age", new XText("25")), new XElement("Gender", new XText("Male"))))); doc.Save(@"C:\sample2.xml");
Example 2 – Using LINQ to XML classes to create an XML document
As you can see, using the XML DOM classes to construct an XML document requires you to declare each component and attach each element to their proper parents one by one. Using the LINQ to XML classes, you can see the every part of the XML document you will create is instantiated inside the constructor of every class. These method of creating XML markup is called functional construction. Each LINQ to XML class’ constructor accepts arguments that may serve as child elements or values of the element it represents. For example, the XElement has the following overload of its constructor:
XElement(XName name, params object content)
The first parameter accepts the name of the element. You can simply pass a string as the name and it will automatically be converted to an XName instance. The second parameter is special because it allows you to pass any number of different kinds of objects such as an XText, XAttribute, or an XElement that will be a child element of that current XElement. Other LINQ to XML class only accepts one argument such as XComment and XText which both accept a string argument that represents the text they will render.
The following table shows some of the LINQ to XML classes you can use together what part of an XML document they represent.
|XDocument||Represents an XML Document|
|XDeclaration||Represents an XML Declaration|
|XElement||Represents an XML Element|
|XAttribute||Represents an attribute of an XML Element|
|XComment||Represents an comment|
|XText||Represents the inner text of an XML element.|
Figure 1 – LINQ to XML Classes
For example, if you want to create an element named Person with a name attribute of value John Smith, here’s the code to do that.
var personElement = new XElement("Person", new XAttribute("name", "John Smith"));
If you want to add a child element for that person, simply add another argument to the constructor of XElement.
var personElement = new XElement("Person", new XAttribute("name", "John Smith"), new XElement("Age", new XText("30")));
The child argument has a name of Age and the next argument to its constructor is its inner text represented by the XText class. You can also see in Example 2 how every XElement argument was indented. This is to make it look more like the way we indent XML elements. You can already see how the XML output will look like simply by looking at the code.
At the end of Example 2 is a call to the XDocument.Save method. This method allows you to save the constructed XML which is currently in memory, into an external XML file. The method accepts a string argument which represents the file path of the file. If the file does not exist, then it will be created. If the file is already there, it will be overwritten. There are other overloads of this method, but for now, this version is sufficient to save the constructed XML to a file.