On Monday I started working through some LINQ to XML and it got me so excited that I misunderstood some project requirements that ended up being quite wrong. It did not, however, diminish my enthusiasm. I ended up using a small part of the code in the end anyway, even though it was not in a production environment.
Lets say you have a collection of XML documents and you would like to know what elements appear in all of them, so at the end of it all you have a single of list of elements that appear between all of them. This is how I did it:
DirectoryInfo di = new DirectoryInfo(ConfigurationManager.AppSettings["XMLDirectory"].ToString());
Dictionary values = new Dictionary();
FileInfo[] fi = di.GetFiles();
Response.Write("
");
Response.Write("
");
foreach (FileInfo file in fi)
{
//Response.Write(@"
");
//Response.Write("" + file.Name + " ");
XmlReaderSettings settings = new XmlReaderSettings();
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
settings.ConformanceLevel = ConformanceLevel.Fragment;
//Console.WriteLine(file.Name);
XmlReader reader = XmlReader.Create(file.Directory + @"\" + file.Name, settings);
XDocument document = XDocument.Load(reader);
IEnumerable elems = from items in document.Descendants("Bond")
select items;
foreach (XElement elem in elems)
{
IEnumerable childElems = from items in elem.Descendants()
select items;
foreach (XElement xelem in childElems)
{
//Response.Write(xelem.Name.ToString() + " " + xelem.Parent.Name.ToString() + " ");
if (!values.ContainsKey(xelem.Name.ToString()))
{
values.Add(xelem.Name.ToString(), xelem.Parent.Name.ToString());
}
}
}
//Response.Write(" |
");
}
Response.Write("
");
Response.Write("
");
Response.Write(@"
| ");
Response.Write("Combined");
var combined = values
.OrderBy(kv => kv.Value);
foreach (KeyValuePair kvp in combined)
{
Response.Write(kvp.Key + " " + kvp.Value + "");
}
Response.Write(" |
");
Response.Write("
");
Response.Write("
");
I use the DirectoryInfo class on a directory, XMLPath in this instance. I then declare an array of type FileInfo, which I then use in a foreach (Enumerate) loop using the FileInfo class. I then use the XMLReader class to read the XML document that is represented through the FileInfo class to read the XML. Inside the foreach loop I create an enumerable instance of XElement called elems which uses LINQ to XML to select all the items. I then create a second enumerable instance of XElements called childElems. I then iterate (enumerate) through the childElems instance and add the Name of the element as the key and the parent as a value to a dictionary of type string,string which I declared earlier. This will loop through all files in the directory and generate a dictionary with combined values. Once its in a dictionary you can simply enumerate through it. I ordered it first by using the OrderBy extension method. Once it has been ordered I enumerate through it with a KeyValuePair and display the combined list. This approach has apparent weaknesses in that it uses the name of a node as a key and the parent as the value. What if two nodes are equal but have different parents? It served a purpose for me though.
The second piece of code I would like to show is an example of converting a dataset to xml and returning the raw XML. Let’s say you have an arbitrary function and you want to return the raw XML of a dataset, you could use:
StringWriter writer = new StringWriter();
transactionDS.WriteXml(writer);
xmlizedString = writer.ToString();
return xmlizedString;