Flatten XML, change node then add to dictionary in C# - c#

Here is part of my very long XML (over 223 nodes)
<ApplicationExtraction>
<ApplicationDate>10/06/2015</ApplicationDate>
<Status>Application Received</Status>
<EquipmentType>Equipment</EquipmentType>
<GetActiveLeaseApplicationParties>
<Item>
<RelationshipType>Primary Lessee</RelationshipType>
<PartyNumber>20000107</PartyNumber>
<FirstName>Parvesh</FirstName>
<LastName>Musharuf</LastName>
<DateOfBirth>12/12/1993</DateOfBirth>
<CreationDate>10/06/2015</CreationDate>
</Item>
<Item>
<RelationshipType>Co-Lessee</RelationshipType>
<PartyNumber>20000108</PartyNumber>
<IsCorporate>No</IsCorporate>
<FirstName>Pary</FirstName>
<LastName>Mushroom</LastName>
<DateOfBirth>1/12/1953</DateOfBirth>
<CreationDate>10/06/2015</CreationDate>
</Item>
</GetActiveLeaseApplicationParties>
</ApplicationExtraction>
I created dictionary Dictionary<string, string> xmlData = new Dictionary<string, string>(); and want to add node as key and node value as value.
I got part of it work until 2nd Item child nodes. It gives me the error of "An item with the same key has already been added". Now I want to add sequence number to the node Item so that I won't get this error. Ideally, I want something like this:
ApplicationExtraction.GetActiveLeaseApplicationParties.Item1.RelationshipType
ApplicationExtraction.GetActiveLeaseApplicationParties.Item1.PartyNumber
ApplicationExtraction.GetActiveLeaseApplicationParties.Item1.FirstName
ApplicationExtraction.GetActiveLeaseApplicationParties.Item2.RelationshipType
ApplicationExtraction.GetActiveLeaseApplicationParties.Item2.PartyNumber
Is it possible to achieve this?
I tried to catch the error and split the string to put number in but don't know how to increase the sequence probably instead I got:
ApplicationExtraction.GetActiveLeaseApplicationParties.Item1.RelationshipType
ApplicationExtraction.GetActiveLeaseApplicationParties.Item2.PartyNumber
ApplicationExtraction.GetActiveLeaseApplicationParties.Item3.FirstName
This is my code. result only contain path(node) and value
foreach (var p in result)
{ try
{ key = p.Path;
value =p.Value;
xmlData.Add(key,value); }
catch (Exception exc)
{ i++;
if (exc.Message == "An item with the same key has already been added.")
{
pos = key.IndexOf("Item");
if (pos !=-1 )
{
strTemp1 = key.Substring(0,key.IndexOf("Item")+4);
strTemp2 = key.Substring(pos + 4,key.Length - pos - 4);
}
key = strTemp1 + "[" + i.ToString() + "]" + strTemp2;
value =p.Value;
xmlData.Add(key,value);
}
}

Did you try to step through in debugger?
Assuming i equals 0 at the top of the loop:
For the first iteration you will add Item.RelationshipType, Item.PartyNumber, etc.
For the second item, you get exception at Item.RelationshipType and you will instead use Item[1].RelationshipType.
For that second item itself, you will then get exception for Item.PartyNumber as well, i will be incremented to 2 and the key you will use will be Item[2].PartyNumber.
This is why you are seeing the keys that you see.
There are multiple ways to get the correct key. One is to keep track of current item number, which you can increment when you see the <item> tag, and use it for all sub-elements.

you can create a List of Tuple
which can collect all the values of the xml.
add each item in the xml,to the list
List.Add(Tuple.Create((Relationship.value,PartyNumber.value...);
To fetch each one in the list, give lst[i].item1,lst[i].item2 which will provide you the xml Item[i].RelationshipValue,Item[i].PartyNumbervalue

Below is how I would do it. If you are getting an error that the key already exists it is due to your dictionary have duplicate keys. I would use the PartyNumber as the key in the dictionary. if you have more than one entry for a part number than the dictionary must be defined as Dictionary>.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication61
{
class Program
{
static void Main(string[] args)
{
string xml =
"<ApplicationExtraction>" +
"<ApplicationDate>10/06/2015</ApplicationDate>" +
"<Status>Application Received</Status>" +
"<EquipmentType>Equipment</EquipmentType>" +
"<GetActiveLeaseApplicationParties>" +
"<Item>" +
"<RelationshipType>Primary Lessee</RelationshipType>" +
"<PartyNumber>20000107</PartyNumber>" +
"<FirstName>Parvesh</FirstName>" +
"<LastName>Musharuf</LastName>" +
"<DateOfBirth>12/12/1993</DateOfBirth>" +
"<CreationDate>10/06/2015</CreationDate>" +
"</Item>" +
"<Item>" +
"<RelationshipType>Co-Lessee</RelationshipType>" +
"<PartyNumber>20000108</PartyNumber>" +
"<IsCorporate>No</IsCorporate>" +
"<FirstName>Pary</FirstName>" +
"<LastName>Mushroom</LastName>" +
"<DateOfBirth>1/12/1953</DateOfBirth>" +
"<CreationDate>10/06/2015</CreationDate>" +
"</Item>" +
"</GetActiveLeaseApplicationParties>" +
"</ApplicationExtraction>";
XDocument doc = XDocument.Parse(xml);
Dictionary<int, Item> dict = new Dictionary<int, Item>();
foreach (XElement item in doc.Descendants("Item").AsEnumerable())
{
Item newItem = new Item() {
relationshipType = item.Element("RelationshipType").Value,
partyNumber = int.Parse(item.Element("PartyNumber").Value),
isCorporate = item.Element("IsCorporate") == null ? false :
item.Element("IsCorporate").Value == "Yes" ? true : false,
firstName = item.Element("FirstName").Value,
lastName = item.Element("LastName").Value,
dateOfBirth = DateTime.Parse(item.Element("DateOfBirth").Value),
creationDate = DateTime.Parse(item.Element("CreationDate").Value)
};
dict.Add(newItem.partNumber, newItem);
}
}
public class Item
{
public string relationshipType { get; set; }
public int partyNumber { get; set; }
public Boolean isCorporate { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public DateTime dateOfBirth { get; set; }
public DateTime creationDate { get; set; }
}
}
}

Related

How do i add database values to a dictionary containing a class as object

I have a dictionary containg a string as TKey and a class "Component" as TValue.
My problem is that a want to add database values and xml values into the class fields.
This is my class Component:
public class Component
{
public string ComponentNr { get; set; }
public string Omschrijving { get; set; }
public int Aantal { get; set; }
public int Pos { get; set; }
}
I already have filled the fields ComponentNr and Pos with xml attribute values and now i want to get the "Aantal" and "Omschrijving" from the database where Database value "artcode" is ComponentNr
the query:
SqlCommand dgCommand = new SqlCommand("select g.artcode, i.Description, sum(g.aantal*-1) as aantal " +
"from gbkmut g " +
"join Items i on g.artcode = i.ItemCode " +
"where 1=1 and g.project=#projectnr and g.reknr=3000 and g.bud_vers='MRP' and g.operation='VOORSMD' and g.artcode !='H MAN' and i.Description not like 'pcb %' " +
"group by g.artcode, i.Description, g.aantal ", conn);
This is what i have at the moment to fill the Dictionary with xml attribute value:
Dictionary<string, Component> resultaten = componenten;
List<string> files = fileList;
string file;
file = files.Find(x => x.Contains(faberNr));
XDocument xdoc = XDocument.Load(file);
List<Component> components = xdoc.Descendants("Part").Select(x => new Component()
{
ComponentNr = (string)x.Elements().Where(y => y.Attribute("PartsName") != null)
.Select(y => (string)y.Attribute("PartsName")).FirstOrDefault(),
Pos = (int)x.Descendants().Where(y => y.Attribute("Setno") != null)
.Select(y => (int)y.Attribute("Setno")).FirstOrDefault()
}).ToList();
resultaten = components.GroupBy(x => x.ComponentNr, y => y).ToDictionary(x => x.Key, y => y.FirstOrDefault());
return resultaten;
Example:
My expected output is:
Key = 38292000
Value = Component
Aantal = 16
ComponentNr = 38292000
Omschrijving = Omschrijving123
Pos = 12
My actual output is:
Key = 38292000
Value = Component
Aantal = 0
ComponentNr = 38292000
Omschrijving = null
Pos = 12
So, step 1 is to populate a Dictionary<string, Component> from xml. Then step 2 is to run a database query to finish filling out the Component objects that are stored in the Dictionary?
ComponentNr is the key into the Dictionary, and you have ComponentNr from your database query in the "artcode" field, so you would just look up the value from the Dictionary using "artcode" then modify it.
// reader is an instance of SqlDataReader you got from the SqlCommand.
// resultaten is the Dictionary<string, Component> that you populated earlier.
// If these columns can be null in the database, don't forget to check them for DBNull.Value.
string componentNr = Convert.ToString(reader["artcode"]);
if (resultaten.TryGetValue(componentNr, out Component value))
{
value.Aantal = Convert.ToInt32(reader["aantal"]);
value.Omschrijving = Convert.ToString(reader["Description"]);
}
else
{
// Component exists in the database but not in the Dictionary.
}

C# XML multiple subchild

Good day! Im trying to parse XML subchild using dataset. The thing is its not reading the "SiteCode" when it has multiple value.
for example:
string filePath = #"" + _clsPathIntervalSttngs.localPath + "/" + "hehe.xml";
DataSet dataSet = new DataSet()
dataSet.ReadXml(filePath, XmlReadMode.InferSchema);
// Then display informations to test
foreach (DataTable table in dataSet.Tables)
{
Console.WriteLine(table);
for (int i = 0; i < table.Columns.Count; ++i)
{
Console.Write("\t" + table.Columns[i].ColumnName.Substring(0, Math.Min(6, table.Columns[i].ColumnName.Length)));
Console.WriteLine();
}
foreach (var row in table.AsEnumerable())
{
for (int i = 0; i < table.Columns.Count; ++i)
{
Console.Write("\t" + row[i]);
}
Console.WriteLine();
}
}
this is what it is returning.
Its returning a 0 value and selecting the Product instead of sitecode.
Where did i go wrong?
You might have to check the code because I just took something similar I had lying around and changed it to look at your document hierarchy. I also didn't use a DataSet. Consider the following code:
var filePath = "<path to your file.xml>";
var xml = XDocument.Load(filePath);
var items = from item in xml.Descendants("Product").Elements()
select item.Value;
Array.ForEach(items.ToArray(), Console.WriteLine);
That should show you the values of each element under product. If you want the whole element, remove the .Value in the select clause of the LINQ query.
Update
I'm now projecting to an anonymous type. You'll get one of these for each Product element in the file.
var items = from item in dataset.Descendants("Product")
select new
{
RefCode = item.Element("RefCode").Value,
Codes = string.Join(", ", item.Elements("SiteCode").Select(x => x.Value)),
Status = item.Element("Status").Value
};
Array.ForEach(items.ToArray(), Console.WriteLine);
I have flattened the codes to a comma separated string but you can keep the IEnumerable or ToList it as you wish.
Using xml Linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication51
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XElement doc = XElement.Load(FILENAME);
List<Product> products = doc.Descendants("Product").Select(x => new Product()
{
refCode = (string)x.Element("RefCode"),
siteCode = x.Elements("SiteCode").Select(y => (int)y).ToArray(),
status = (string)x.Element("Status")
}).ToList();
}
}
public class Product
{
public string refCode { get; set; }
public int[] siteCode { get; set; }
public string status { get; set; }
}
}

CSV Delimited to XML - Folder Hierarchy

This is my first time posting so I apologize for any ignorance or failed use of examples.
I have a console app project to create where I have been given a fair few CSV files and I need to create some kind of Parent/Child/Grandchild relationship out of them (XML? maybe? - then I can use that to do the uploads and writes to the DMS with minimal calls - I don't want to be querying if a folder exists over and over)
I am a little out of my depth on this one
I need to know the best way to do this without 3rd party library dependencies, pure C#, using the OLEDB JET provider is most likely required as it will handle the parsing required, there is no order to the CSV files in regards to date, previous years could appear down the list and vice versa.
Here's an example of the CSV output
"DESCRIPTION1","8, 5/8\" X 6.4MM","STRING","filename001.pdf","2016-09-19","1"
"DESCRIPTION2","12, 3/4\" X 6.4MM","STRING","filename001.pdf","2016-09-19","1"
"DESCRIPTION3","12, 3/4\" X 6.4MM","STRING","filename001.pdf","2016-09-19","1"
"another description 20# gw","1","388015","Scan123.pdf","2015-10-24","1"
"another description 20# gw","3","385902","Scan456.pdf","2015-04-14","1"
"STRINGVAL1","273.10 X 9.27 X 6000","45032-01","KHJDWNEJWKFD9101529.pdf","2012-02-03","1"
"STRINGVAL2","273.10 X 21.44 X 6000","7-09372","DJSWH68767681540.pdf","2017-02-03","1"
The end output will be (YEAR/MONTH/FILENAME + (Attributes for each file - these are for eventually updating columns inside a DMS))
Year and Month retrieved from the column with the date
If the YEAR alread exists then it will not be created again
If the month under that year exists it will not be created again
If the filename already exists under that YEAR/MONTH it will not be created again BUT the additional ATTRIBUTES for that FileName will be added to the attributes - "line seperated?"
Required Output:
I have attempted a Linq query to begin to output the possible required XML for me to progress but it outputs every row and does no grouping, I am not familiar with Linq at the moment.
I also ran into issues with the basic escaping on the .Split(',') doing it this way (see original CSV examples above compared to me using TAB separation in my test file and example below) which is why I want the Oledb provider to handle it.
string[] source = File.ReadAllLines(#"C:\Processing\In\mockCsv.csv");
XElement item = new XElement("Root",
from str in source
let fields = str.Split('\t')
select new XElement("Year", fields[4].Substring(0, 4),
new XElement("Month", fields[4].Substring(5, 2),
new XElement("FileName", fields[3]),
new XElement("Description",fields[0]),
new XElement("Length", fields[1]),
new XElement("Type", fields[2]),
new XElement("FileName", fields[3]),
new XElement("Date", fields[4]),
new XElement("Authorised", fields[5]))
)
);
I also need to log every step of the process so I have setup a Logger class
private class Logger
{
private static string LogFile = null;
internal enum MsgType
{
Info,
Debug,
Error
}
static Logger()
{
var processingDetails = ConfigurationManager.GetSection(SECTION_PROCESSINGDETAILS) as NameValueCollection;
LogFile = Path.Combine(processingDetails[KEY_WORKINGFOLDER],
String.Format("Log_{0}.txt", StartTime.ToString("MMMyyyy")));
if (File.Exists(LogFile))
File.Delete(LogFile);
}
internal static void Write(string msg, MsgType msgType, bool isNewLine, bool closeLine)
{
if (isNewLine)
msg = String.Format("{0} - {1} : {2}", DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss"), msgType, msg);
if (closeLine)
Console.WriteLine(msg);
else
Console.Write(msg);
if (String.IsNullOrEmpty(LogFile))
return;
try
{
using (StreamWriter sw = new StreamWriter(LogFile, true))
{
if (closeLine)
sw.WriteLine(msg);
else
sw.Write(msg);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
Used as such
Logger.Write(String.Format("Reading records from csv file ({0})... ",
csvFile), Logger.MsgType.Info, true, false);
Try following. If you are reading from a file use StreamReader instead of StringReader :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
using System.Text.RegularExpressions;
namespace ConsoleApplication74
{
class Program
{
static void Main(string[] args)
{
string input =
"\"DESCRIPTION1\",\"8, 5/8 X 6.4MM\",\"STRING\",\"filename001.pdf\",\"2016-09-19\",\"1\"\n" +
"\"DESCRIPTION2\",\"12, 3/4 X 6.4MM\",\"STRING\",\"filename001.pdf\",\"2016-09-19\",\"1\"\n" +
"\"DESCRIPTION3\",\"12, 3/4 X 6.4MM\",\"STRING\",\"filename001.pdf\",\"2016-09-19\",\"1\"\n" +
"\"another description 20# gw\",\"1\",\"388015\",\"Scan123.pdf\",\"2015-10-24\",\"1\"\n" +
"\"another description 20# gw\",\"3\",\"385902\",\"Scan456.pdf\",\"2015-04-14\",\"1\"\n" +
"\"STRINGVAL1\",\"273.10 X 9.27 X 6000\",\"45032-01\",\"KHJDWNEJWKFD9101529.pdf\",\"2012-02-03\",\"1\"\n" +
"\"STRINGVAL2\",\"273.10 X 21.44 X 6000\",\"7-09372\",\"DJSWH68767681540.pdf\",\"2017-02-03\",\"1\"\n";
string pattern = "\\\"\\s*,\\s*\\\"";
string inputline = "";
StringReader reader = new StringReader(input);
XElement root = new XElement("Root");
while ((inputline = reader.ReadLine()) != null)
{
string[] splitLine = Regex.Split(inputline,pattern);
Item newItem = new Item() {
description = splitLine[0].Replace("\"",""),
length = splitLine[1],
type = splitLine[2],
filename = splitLine[3],
date = DateTime.Parse(splitLine[4]),
authorized = splitLine[5].Replace("\"", "") == "1" ? true : false
};
Item.items.Add(newItem);
}
foreach(var year in Item.items.GroupBy(x => x.date.Year).OrderBy(x => x.Key))
{
XElement newYear = new XElement("_" + year.Key.ToString());
root.Add(newYear);
foreach(var month in year.GroupBy(x => x.date.Month).OrderBy(x => x.Key))
{
XElement newMonth = new XElement("_" + month.Key.ToString());
newYear.Add(newMonth);
newMonth.Add(
month.OrderBy(x => x.date).Select(x => new XElement(
x.filename,
string.Join("\r\n", new object[] {
x.description,
x.length,
x.type,
x.date.ToString(),
x.authorized.ToString()
}).ToList()
)));
}
}
}
}
public class Item
{
public static List<Item> items = new List<Item>();
public string description { get; set; }
public string length { get; set; }
public string type { get; set; }
public string filename { get; set; }
public DateTime date { get; set; }
public Boolean authorized { get; set; }
}
}

Unable to access items in c# array (For cs:go trading bot)

im reprogramming the tf2 tradebot by JesseCar 96 for CS:go. Im trying to get the items stored in a list array and I can't figure out how to access it. The instantiation and item data works like this:
public class TradeUserAssets : IEquatable<TradeUserAssets>, IComparable<TradeUserAssets>
{
/// <summary>Inventory type</summary>
public long contextid { get; private set; }
/// <summary>itemid</summary>
public ulong assetid { get; private set; }
public int appid { get; private set; }
public int amount { get; private set; }
public TradeUserAssets(int appid, long contextid, ulong assetid, int amount = 1)
{
this.appid = appid;
this.contextid = contextid;
this.assetid = assetid;
this.amount = amount;
}}
It is instantiated through:
private List<TradeUserAssets> otherOfferedItems;
otherOfferedItems = new List<TradeUserAssets>();
But when I use this foreach loop to get the data
foreach (long contextid in Trade.OtherOfferedItems.ToString())
{
Console.WriteLine(contextid);
}
The bot crashes. I've tried using a for loop and using the index number after .ToString()[i] like this but I can't get any of the data out. If I do anything other than .ToString() after OtherOfferedItems it won't build. Any help is really appreciated!
EDIT: This is my userHandler.cs
string tradeid;
if (myItems.Count == 0)
{
offer.Accept(out tradeid);
Log.Success("Accepted trade offer successfully : Trade ID: " + tradeid);
foreach (asset in Trade.OtherOfferedItems)
{
Console.WriteLine(asset);
}
using (var connection = new MySqlConnection("Server=localhost;Database=skindump;Uid=USERNAME;Pwd=PASSWORD;"))
{
var time = DateTime.Now.TimeOfDay;
var date = DateTime.Now;
date.ToString();
connection.Open();
MySqlCommand cmd = new MySqlCommand("INSERT INTO trades (tradeID, tradeUsed, tradeDate, steamID) VALUES (" + tradeid + ", 1, '" + date + "', '" + OtherSID.ConvertToUInt64() + "');");
cmd.Connection = connection;
cmd.ExecuteNonQuery();
Console.WriteLine("ServerVersion: {0}", connection.ServerVersion);
Console.WriteLine(date);
connection.Close();
}
}
Line 201 is the open squiggly bracket after the mysql connection (var connection = new mysql connection etc...). When I comment out the foreach loop it runs fine without crashing so thats definitely the issue.
You probably want to access a property inside of each object of your list. But what you are doing is just converting the Trade.OtherOfferedItems list to a string and then looping over that. You probably want to do something like this instead:
foreach (TradeUserAssets asset in Tade.OtherOfferedItems)
{
Console.WriteLine(asset.contextid);
}
You're trying to access the contextid by using ToString(), which is the wrong way to do it.
Instead, iterate through the collection of TradeUserAssets, and access the property inside the loop.
foreach (var asset in Trade.OtherOfferedItems)
{
Console.WriteLine(asset.contextid);
}
The reason your current code compiles is because it's returning the ascii value for each character in the string that ToString() returns (which is just the class name of the collection). Even if it didn't crash the app at runtime, it wouldn't be what you want.

C# Looping through nested LINQ select statements

The sample below is parsing an XML document then looping through the members and storing them in a list of objects (The data ultimately ends up in an SQL database):
public static void Parse(XDocument xml)
{
XNamespace ns = "http://somenamespace.com/ns";
var Locations =
from Continents in xml.Descendants(ns + "Continent")
from Countries in Continents.Elements(ns + "Country")
select new
{
Continent1 = (string) Continents.Element(ns + "Europe"),
Country1 = (string) Countries.Element(ns + "United_Kingdom"),
Cities = from Cities in Countries.Elements(ns + "City")
select new
{
City1 = (string) Cities.Element(ns + "London")
}
};
List<Location> locationColl = new List<Location>();
loc_Entity_FrameworkContainer context = new loc_Entity_FrameworkContainer();
var i = 0;
foreach (var location in Locations)
{
Location l = new Location();
locationColl.Add(l);
locationColl[i].Continent = (string) location.Continent1;
locationColl[i].Country = (string) location.Country1;
locationColl[i].City = (string) location.City1; // Can't access "City1"
context.Location.Add(locationColl[i]);
i++;
}
context.SaveChanges();
}
The statement: locationColl[i].City = (string)location.City1;
doesn't find "City1". (This is the issue, I can't access all the members from "Locations" in one loop)
Location Class:
namespace locationProject
{
using System;
using System.Collections.Generic;
public partial class Location
{
public string Continent { get; set; }
public string Country { get; set; }
public string City { get; set; }
}
}
XML Example:
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns:ns="http://somenamespace.com/ns">
<ns:Continent>
<ns:Europe>21c99a56-4b3d-4571-802a-76cdb6b81a01</ns:Europe>
<ns:Country>
<ns:United_Kingdom>eb2e9eec-dc3b-4636-bcf5-dba0024e62f3</ns:United_Kingdom>
<ns:City>
<ns:London>109b48ec-d829-4a87-b200-4dc9a94db48c</ns:London>
</ns:City>
</ns:Country>
</ns:Continent>
<ns:Continent>
<ns:Europe>a11ed925-dc0d-4dfd-b1c2-52eb697ad689</ns:Europe>
<ns:Country>
<ns:United_Kingdom>a61d02ef-7b80-4390-926a-49c6d9af9634</ns:United_Kingdom>
<ns:City>
<ns:London>dbb9c5cc-b08f-4223-b32c-acb4ed9ce97c</ns:London>
</ns:City>
</ns:Country>
</ns:Continent>
</feed>
I'm trying to find a way of looping through all the elements (Continent1, Country1, City1) that doesn't involve multiple loops and doesn't break the nested structure of the LINQ statements.
There are questions on here similar to this one, but I haven't found one I understand well enough to integrate with my code.
Thanks a lot!
Your anonymous type contained in the Locations list has a .Cities property that contains a City1 member:
Cities = from Cities in Countries.Elements(ns + "City")
select new
{
City1 = (string) Cities.Element(ns + "London")
}
Try this:
var Locations =
from Continents in xml.Descendants(ns + "Continent")
from Countries in Continents.Elements(ns + "Country")
from Cities in Countries.Elements(ns + "City")
select new
{
Continent1 = (string) Continents.Element(ns + "Europe"),
Country1 = (string) Countries.Element(ns + "United Kingdom"),
City1 = (string) Cities.Element(ns + "London")
};

Categories