c#: Создание и заполнение treeview из нескольких таблиц Mysql
-
16 марта 2012 г. 15:46
Здравствуйте. И сразу к делу...
Есть 4 таблицы mysql:
CREATE TABLE `HR`.`Department` ( `Dept_code` int(11) NOT NULL, `Parent_Dept_code` int(11) NOT NULL, `Full_name_d` varchar(250) NOT NULL, `Short_name_d` varchar(80), PRIMARY KEY (`Dept_code`)); CREATE TABLE `HR`.`post` ( `Post_code` int(11) NOT NULL, `Full_name_p` varchar(250) NOT NULL, `Short_name_p` varchar(80), `Chief_code` int, PRIMARY KEY (`Post_code`)); CREATE TABLE `HR`.`Staff` ( `Personal_n` INT(11) NOT NULL, `LName` VARCHAR(60) NOT NULL, `FName` VARCHAR(30) NOT NULL, `Mname` VARCHAR(40) NOT NULL, PRIMARY KEY (`Personal_n`)); CREATE TABLE `HR`.`Relation` ( `idrelation` int(11) NOT NULL, `staff_rel` INT(11) NOT NULL, `Dept_code_rel` int(11) NOT NULL, `Post_code_rel` int(11) NOT NULL, PRIMARY KEY (`idrelation`), FOREIGN KEY (`staff_rel`) REFERENCES staff (`Personal_n`), FOREIGN KEY (`Dept_code_rel`) REFERENCES Department (`Dept_code`), FOREIGN KEY (`Post_code_rel`) REFERENCES Post (`Post_code`));
Нужно чтобы при запуске программы (VS2010, c#) создавался treeview на основании всех этих таблиц...
Должно быть что-то вроде:(2 отдела (в отделе post - staff) в них по несколько бюро, в каждом бюро несколько post и за каждым Personal_n закреплён свой Post_code (названия post повторяются):
-department (отдел)
- post
-staff
-department(бюро)
- post
-staff
- post
-staff
-staff
и т.д. всё заново...Вот каким образом я вывел отделы:
Здесь есть поле parent_dept_code, что существенно упрощает задачу. А таблицы staff, post и department связанны только через таблицу relation.public MySqlConnection myConnection; string Connect = "Database=HR;Data Source=localhost;User Id=root;Password=root"; MySqlDataAdapter Adapt; private void Form1_Load(object sender, EventArgs e) { try { myConnection = new MySqlConnection(Connect); myConnection.Open(); DataTable dtTree = new DataTable(); string sql = "select Dept_code, Parent_Dept_code, Short_name_d from `hr`.`department`"; Adapt = new MySqlDataAdapter(sql, myConnection); Adapt.Fill(dtTree); Adapt.Dispose(); treeView1.BeginUpdate(); treeView1.Nodes.Clear();
CreateTreeView(treeView1.Nodes, 0, dtTree); treeView1.Nodes[0].Expand(); treeView1.Select(); treeView1.EndUpdate(); myConnection.Close(); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } protected void CreateTreeView(TreeNodeCollection parentNode, int parentID, DataTable mytab) { foreach (DataRow dta in mytab.Rows) { if (Convert.ToInt32(dta["Parent_Dept_code"]) == parentID) { String key = dta["Dept_code"].ToString(); String text = dta["Short_name_d"].ToString(); TreeNodeCollection newParentNode = parentNode.Add(key, text).Nodes; CreateTreeView(newParentNode, Convert.ToInt32(dta["Dept_code"]), mytab); } } }
Помогите, а то уже неделю голову ломаю... желательно с конкретными примерами.
- Изменено vantur 16 марта 2012 г. 15:52
Все ответы
-
16 марта 2012 г. 19:52Модератор"Помогите, а то уже неделю голову ломаю... желательно с конкретными примерами." - А в чём собственно проблема? Нужно её понять, чтобы попытаться решить.
-
17 марта 2012 г. 6:12
Нужно чтобы при запуске программы (VS2010, c#) создавался treeview на основании всех этих таблиц...
это по ламерски, а мне нужно что бы при запуске программы treeview создавался и заполнялся полностью без помощи пользователя. На сколько я понял нужно использовать рекурсию. И тут проблемка, что одной должности со своим id соответствует свой id сотрудника, но названия должностей совпадают...//добавление должности по селекту бюро private void treeView1_AfterSelect(object sender, TreeViewEventArgs e) { myConnection = new MySqlConnection(Connect); myConnection.Open(); DataTable dtTree = new DataTable(); string sql = "select Short_name_p from `hr`.`department`, `hr`.`post`, `hr`.`relation`, `hr`.`staff` where (post_code=post_code_rel) and (dept_code=dept_code_rel) and (Personal_n=Staff_rel) and (Short_name_d='" + treeView1.SelectedNode.Text + "')"; Adapt = new MySqlDataAdapter(sql, myConnection); Adapt.Fill(dtTree); Adapt.Dispose(); foreach (DataRow dta in dtTree.Rows) { TreeNode childNode = new TreeNode(dta["Short_name_p"].ToString()); treeView1.SelectedNode.Nodes.Add(childNode); } myConnection.Close(); } // добавление сотрудника по NodeMouseDoubleClick должности private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) { myConnection = new MySqlConnection(Connect); myConnection.Open(); DataTable dtTree = new DataTable(); string sql = "select Lname,FName,MName from `hr`.`department`,`hr`.`post`, `hr`.`relation`, `hr`.`staff` where (post_code=post_code_rel) and (dept_code=dept_code_rel) and (Personal_n=Staff_rel) and (Short_name_p='" + treeView1.SelectedNode.Text + "')"; Adapt = new MySqlDataAdapter(sql, myConnection); Adapt.Fill(dtTree); Adapt.Dispose(); foreach (DataRow dta in dtTree.Rows) { TreeNode childNode = new TreeNode(dta["Lname"].ToString() + " " + dta["FName"].ToString() + " " + dta["MName"].ToString()); treeView1.SelectedNode.Nodes.Add(childNode); } myConnection.Close(); }Должно быть:
-
17 марта 2012 г. 7:49Модератор
Для начала нужно попытаться правильно организовать структуру бд, чтобы потом избежать сложностей с написанием кода. Правильная сруктура БД - одна из важнейших составляющих. Попытаюссь понять как организована ваша база.
/*Таблица отделов, один отдел может содержать другие т.е. отношение предок - потомок? Если так то тут нужны возвратные(рекурсивные) отнощения. В вашем случае Parent_Dept_code должен быть внешним по отношению к Dept_code. Т.е. FOREIGN KEY (`Parent_Dept_code`) REFERENCES Department (`Dept_code`). */ CREATE TABLE `HR`.`Department` ( `Dept_code` int(11) NOT NULL, `Parent_Dept_code` int(11) NOT NULL, `Full_name_d` varchar(250) NOT NULL, `Short_name_d` varchar(80), PRIMARY KEY (`Dept_code`)); CREATE TABLE `HR`.`post` ( `Post_code` int(11) NOT NULL, `Full_name_p` varchar(250) NOT NULL, `Short_name_p` varchar(80), `Chief_code` int, /*Что за код?*/ PRIMARY KEY (`Post_code`)); /* Один сотрудник может иметь несколько должностей, или нет? */ CREATE TABLE `HR`.`Staff` ( `Personal_n` INT(11) NOT NULL, `LName` VARCHAR(60) NOT NULL, `FName` VARCHAR(30) NOT NULL, `Mname` VARCHAR(40) NOT NULL, PRIMARY KEY (`Personal_n`)); CREATE TABLE `HR`.`Relation` ( `idrelation` int(11) NOT NULL, `staff_rel` INT(11) NOT NULL,/*Если столбец не нулевой, значит если есть должность и сотрудник должен быть, а если место свободное, или такого не бывает? */ `Dept_code_rel` int(11) NOT NULL, `Post_code_rel` int(11) NOT NULL, PRIMARY KEY (`idrelation`), FOREIGN KEY (`staff_rel`) REFERENCES staff (`Personal_n`), FOREIGN KEY (`Dept_code_rel`) REFERENCES Department (`Dept_code`), FOREIGN KEY (`Post_code_rel`) REFERENCES Post (`Post_code`));
-
17 марта 2012 г. 10:10дело в том что данные таблицы я загоняю в mysql из xml-файла, который мне нельзя менять...
Chief_code - это код, который описывает принадлежность данной должности к главной должности отдела, в моём случае начальник управления. т.е. все должности подчиняются должности начальника управления... -
17 марта 2012 г. 17:10
> Нужно чтобы при запуске программы (VS2010, c#) создавался treeview на основании всех этих таблиц... [...] -department (отдел) - post - staff ...
примерно так:
using System.Data; using System.IO; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { var ds = new DataSet("org"); ds.ReadXml(new StringReader(@" <!-- test --> <departament name='d1'> <post name='p1'> <staff name='fio1' /> </post> <departament name='d2'> <post name='p2'> <staff name='fio2' /> <staff name='fio3' /> </post> </departament> <departament name='d3'> <post name='p3' /> </departament> <departament name='d4' /> </departament>")); foreach (DataTable dt in ds.Tables) foreach (DataColumn dc in dt.Columns) if (dc.ColumnMapping == MappingType.Hidden) dc.ColumnMapping = MappingType.Element; this.Size = new System.Drawing.Size(900, 700); var sc = new SplitContainer { Parent = this, Dock = DockStyle.Fill, SplitterDistance = (int)(this.Width * .45) }; var dg = new DataGrid { DataSource = ds, Dock = DockStyle.Fill, Parent = sc.Panel2, ReadOnly = true }; new RichTextBox { Parent = sc.Panel2, Dock = DockStyle.Bottom, Height = 350, Text = ds.GetXml() }; var tv = new TreeView { Dock = DockStyle.Fill, Parent = sc.Panel1 }; foreach (DataRow dr in ds.Tables["departament"].Rows) if (dr.GetParentRow("departament_departament") == null) Fill(tv.Nodes, dr); tv.ExpandAll(); this.Shown += (s, e) => { dg.Focus(); SendKeys.SendWait("%({DOWN})"); tv.Focus(); }; } private static void Fill(TreeNodeCollection nodes, DataRow dr) { var dn = nodes.Add((string)dr["name"]); var ps = dr.GetChildRows("departament_post"); if (ps != null) foreach (DataRow pr in ps) { var pn = dn.Nodes.Add((string)pr["name"]); var ss = pr.GetChildRows("post_staff"); if (ss != null) foreach (DataRow sr in ss) pn.Nodes.Add((string)sr["name"]); } var ds = dr.GetChildRows("departament_departament"); if (ds != null) foreach (DataRow cr in ds) Fill(dn.Nodes, cr); } } }- Помечено в качестве ответа Abolmasov DmitryMicrosoft Community Contributor 21 марта 2012 г. 12:42
-
18 марта 2012 г. 6:50Но данный пример составляет treview из xml и в таком же виде выводит, а мне нужно выводить информацию между тегами, а не их самих (смотрите рисунок выше). Можно немного пояснить код или создать пример именно для решения моей задачи? спс...
- Изменено vantur 18 марта 2012 г. 7:02
-
18 марта 2012 г. 7:53> данный пример составляет treview из xml и в таком же виде выводит
пример выводит данные из DataSet. как они попадают в DataSet не имеет значения.
данные могут быть загружены из xml (как в примере) или из базы данных.
-
19 марта 2012 г. 7:07
Т.е. вам нужно загрузить вашу базу полностью в DataSet с сохранением отношений между таблицами (можно в проект в Solution Explorer добавить новый элемент DataSet, после открыть его в дизайнере и перетащить из Server Explorer необходимы таблицы, после чего проверить связи между ними; далее в коде заполнить DataSet с помощью сгененрированных TableAdapter-ов) . А после уже воспользоваться возможностями получения родительский/дочерних строк для заполнения treeview.
Если ответ Malobukv решает вашу проблему, то пожалуйста, не забудьте отметить его как ответ (кнопка под сообщением).
Спасибо.
Для связи [mail]
- Предложено в качестве ответа Naomi NMicrosoft Community Contributor 5 апреля 2012 г. 0:56
-
22 марта 2012 г. 22:50
Вот что у меня получилось с использованием DataSet:
private void button5_Click(object sender, EventArgs e) { this.postTableAdapter1.Fill(this.hrDataSet.post); this.departmentTableAdapter1.Fill(this.hrDataSet.department); this.relationTableAdapter1.Fill(this.hrDataSet.relation); this.staffTableAdapter1.Fill(this.hrDataSet.staff); foreach (DataRow dr in this.hrDataSet.relation.Rows) // сначала пробежал по всем строкам главной таблицы { TreeNode node = new TreeNode(); string n = dr["dept_code_rel"].ToString(); // пробегаюсь по строкам подчиненной таблицы, но только по тем, которые относятся к текущей строке главной таблицы foreach (DataRow r in this.hrDataSet.department.Select("dept_code = " + n)) { node.Text = r["Short_name_d"].ToString(); treeView2.Nodes.Add(node); TreeNode node1 = new TreeNode(); node1.Name = dr["post_code_rel"].ToString(); foreach (DataRow r1 in this.hrDataSet.post.Select("post_code = " + node1.Name)) { node1.Text = r1["Short_name_p"].ToString(); node.Nodes.Add(node1); TreeNode node2 = new TreeNode(); node2.Name = dr["staff_rel"].ToString(); foreach (DataRow q in this.hrDataSet.staff.Select("personal_n = " + node2.Name)) { node2.Text = q["LName"].ToString() + " " + q["FName"].ToString() + " " + q["MName"].ToString(); node1.Nodes.Add(node2); } } } } }Слева изображена приблезительная структура, которая должна быть. Справа - то что получилось по приведённому коду
Т.е, что должно быть:
- -управление
- -начальник управления
- - ФИО
- - экономист
- - ФИО
- - отдел АСУП
- - начальник отдела
- - фио
- - бюро *
- - Должность (может повторяться)
- - фио
- - отдел САПР
- - начальник отдела
- - фио
- - бюро *
- -должность
- - фио
Для построения такой структуры нужно как-то изменить приведённый код с использованием рекурсии, но я в ней вообще ничего не понимаю.
Исправте, пожалуйста, код с использование рекурсии или хотя бы приведите примеры для моего случая. СПС...- Изменено vantur 22 марта 2012 г. 22:52
-
23 марта 2012 г. 5:09> Для построения такой структуры нужно как-то изменить приведённый код ...
можно ли изменить структуру базы? что возвращает метод this.hrDataSet.GetXml()?
-
23 марта 2012 г. 10:11Структуру желательно не менять, так как все данные и сами таблицы беру из xml. А где вы увидели в предыдущем коде метод this.hrDataSet.GetXml()???
-
23 марта 2012 г. 13:33> А где вы увидели в предыдущем коде метод this.hrDataSet.GetXml()?
покажите xml, который возвращает метод GetXml. возможно, что проще заполнить TreeView на основе xml, а не на основе DataSet.
-
23 марта 2012 г. 14:02
<?xml version=""1.0""?><ns0:Enterprise Date=""13.02.1000"" xmlns:ns0=""http://SAPToAISApplication.SAPData""> <Classifiers> <Classifier_Titles> <Title> <Title_Code>70011946</Title_Code> <Full_Name>НАЧАЛЬНИК УПРАВЛЕНИЯ</Full_Name> <Short_Name>НАЧАЛЬНИК УПРАВЛЕНИЯ</Short_Name> <Date_From>01.01.1900</Date_From> <Date_To>31.12.9999</Date_To> </Title> </Classifier_Titles> <Classifier_Staff> <Staff> <Personal_Number>00034893</Personal_Number> <LName>Фамилия</LName> <FName>Имя</FName> <MName>Отчество</MName> <Date_From>09.01.2012</Date_From> <Date_To>31.12.9999</Date_To> </Staff> </Classifier_Staff> <Classifier_Department> <Department> <Dept_Code>51001583</Dept_Code> <Parent_Dept_Code>00000000</Parent_Dept_Code> <Full_Name>УПРАВЛЕНИЕ</Full_Name> <Short_Name>УПРАВЛЕНИЕ</Short_Name> <Date_From>00.00.0000</Date_From> <Date_To>00.00.0000</Date_To> </Department> </Classifier_Department> </Classifiers> <Relation_Staff_Department_Titles_Vice> <Relation> <Personal_Number>00034844</Personal_Number> <Dept_Code>51001586</Dept_Code> <Titles_Codes> <Title_Code>70011946</Title_Code> </Titles_Codes> </Relation> </Relation_Staff_Department_Titles_Vice> </ns0:Enterprise>";
Вот пример по 1 сотруднику. Всего 90... Что должно быть смотрите выше... -
25 марта 2012 г. 19:34
> Вот пример по 1 сотруднику.
примерно так:
using System.Windows.Forms; using System.Xml.Linq; using System.Xml.XPath; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { var tv = new TreeView { Parent = this, Dock = DockStyle.Fill }; var xe = XElement.Load("data.xml"); foreach (var d in xe.XPathSelectElements("//Department[Parent_Dept_Code='00000000']")) Run(d, tv.Nodes); tv.ExpandAll(); } void Run(XElement d, TreeNodeCollection nc) { var dc = d.Element("Dept_Code").Value; var nn = nc.Add(d.Element("Full_Name").Value); var re = d.XPathSelectElement("//Relation[Dept_Code/text()='" + dc + "']"); var pn = re.Element("Personal_Number"); foreach(var t in re.Element("Titles_Codes").Elements("Title_Code")) { foreach(var x in d.XPathSelectElements("//Title[Title_Code='" + t.Value + "']")) { var s = nn.Nodes.Add(x.Element("Full_Name").Value); var p = x.XPathSelectElement("//Staff[Personal_Number='" + pn.Value + "']"); if(p != null) s.Nodes.Add(p.Element("LName").Value); } } foreach (var s in d.XPathSelectElements("//Department[Parent_Dept_Code='" + dc + "']")) Run(s, nn.Nodes); } } }
-
25 марта 2012 г. 22:54
Извините, но изменились поля в xml. При разборе вашего кода и замене на нужные имена полей почти в каждой строчке выдаёт ошибку: Object reference not set to an instance of an object.
Вот новый xml... Что нужно изменить в вашем коде? СПС...
<?xml version="1.0" encoding="utf-8"?> <ns0:Enterprise Date="13.02.2012" xmlns:ns0="http://SAPToAISApplication.SAPData"> <Classifiers> <Classifier_Titles> <Title> <Title_Code>70011946</Title_Code> <Full_Name>НАЧАЛЬНИК УПРАВЛЕНИЯ</Full_Name> <Short_Name>НАЧАЛЬНИК УПРАВЛЕНИЯ</Short_Name> <Date_From>01.01.1900</Date_From> <Date_To>31.12.9999</Date_To> </Title> </Classifier_Titles> <Classifier_Staff> <Staff> <Personal_Number>00034893</Personal_Number> <LName>Фамилия</LName> <FName>Имя</FName> <MName>Отчество</MName> <Date_From>09.01.2012</Date_From> <Date_To>31.12.9999</Date_To> </Staff> </Classifier_Staff> <Classifier_Department> <Department> <Dept_Code>51001583</Dept_Code> <Parent_Dept_Code>00000000</Parent_Dept_Code> <Full_Name1>УПРАВЛЕНИЕ ИНФОРМАЦИОННЫХ СИСТЕМ</Full_Name1> <Short_Name1>УИС</Short_Name1> <Date_From>00.00.0000</Date_From> <Date_To>00.00.0000</Date_To> </Department> </Classifier_Department> </Classifiers> <Relation_Staff_Department_Titles_Vice> <Relation> <Personal_Number1>00034893</Personal_Number1> <Dept_Code1>51001586</Dept_Code1> <Titles_Codes> <Title_Code2>70011946</Title_Code2> </Titles_Codes> </Relation> </Relation_Staff_Department_Titles_Vice> </ns0:Enterprise>
-
26 марта 2012 г. 5:31
> изменились поля в xml. [...] Вот новый xml... Что нужно изменить в вашем коде?
using System.Windows.Forms; using System.Xml.Linq; using System.Xml.XPath; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { var tv = new TreeView { Parent = this, Dock = DockStyle.Fill }; var xe = XElement.Load("data.xml"); foreach (var d in xe.XPathSelectElements("//Department[Parent_Dept_Code='00000000']")) Run(d, tv.Nodes); tv.ExpandAll(); } void Run(XElement d, TreeNodeCollection nc) { var dc = d.Element("Dept_Code").Value; var nn = nc.Add(d.Element("Full_Name1").Value); var re = d.XPathSelectElement("//Relation[Dept_Code1/text()='" + dc + "']"); var pn = re.Element("Personal_Number1"); foreach(var t in re.Element("Titles_Codes").Elements("Title_Code2")) { foreach(var x in d.XPathSelectElements("//Title[Title_Code='" + t.Value + "']")) { var s = nn.Nodes.Add(x.Element("Full_Name").Value); var p = x.XPathSelectElement("//Staff[Personal_Number='" + pn.Value + "']"); if(p != null) s.Nodes.Add(p.Element("LName").Value); } } foreach (var s in d.XPathSelectElements("//Department[Parent_Dept_Code='" + dc + "']")) Run(s, nn.Nodes); } } }
код работает, если в xml: "<Dept_Code1>51001586</Dept_Code1>" заменить на "<Dept_Code1>51001583</Dept_Code1>" - иначе нет связи между департаментом и должностью.
-
26 марта 2012 г. 16:52
Всё равно ошибка в строке var pn = re.Element("Personal_Number1");
Не могу понять в чём дело... Вот весь xml. Посмотрите чё не так... СПС...
-
26 марта 2012 г. 17:28
> ошибка в строке varpn =re.Element("Personal_Number1");
т.к. бывает, чтор re == null -- в ситуации, когда у подразделения нет должностей.
решение:using System.Windows.Forms; using System.Xml.Linq; using System.Xml.XPath; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { this.Size = new System.Drawing.Size(600, 800); var tv = new TreeView { Parent = this, Dock = DockStyle.Fill }; var xe = XElement.Load("..\\..\\data.xml"); foreach (var d in xe.XPathSelectElements("//Department[Parent_Dept_Code='00000000']")) Run(d, tv.Nodes); tv.ExpandAll(); } void Run(XElement d, TreeNodeCollection nc) { var dc = d.Element("Dept_Code").Value; var nn = nc.Add(d.Element("Full_Name1").Value); var re = d.XPathSelectElement("//Relation[Dept_Code1/text()='" + dc + "']"); if (re != null) { var pn = re.Element("Personal_Number1"); foreach (var t in re.Element("Titles_Codes").Elements("Title_Code2")) { foreach (var x in d.XPathSelectElements("//Title[Title_Code='" + t.Value + "']")) { var s = nn.Nodes.Add(x.Element("Full_Name").Value); var p = x.XPathSelectElement("//Staff[Personal_Number='" + pn.Value + "']"); if (p != null) s.Nodes.Add(p.Element("LName").Value); } } } foreach (var s in d.XPathSelectElements("//Department[Parent_Dept_Code='" + dc + "']")) Run(s, nn.Nodes); } } }- Предложено в качестве ответа Malobukv 27 марта 2012 г. 14:45
-
26 марта 2012 г. 22:04
СПС. Данный код работает. Только вот почему-то не вывело начальника отдела АСУП???
Но он выводит только отделы и их начальников, а мне нужно все должности по отделам, примерно как на скрине:
Нужно выводить начальников отделов и должности этого отдела, которые не должны повторяются в пределах этого бюро (на скрине они повторяются, что не верно)
Т.е., к примеру, ветка Инж. программист 1К, Инж. программист 2К в каком-то бюро должна быть одна и содержать сотрудников этого бюро по этой должности. И так для всех бюро и должностей.
- Изменено vantur 26 марта 2012 г. 22:07
-
27 марта 2012 г. 14:45
> Нужно выводить начальников отделов и должности этого отдела, которые не должны повторяются в пределах этого бюро
using System; using System.Linq; using System.Windows.Forms; using System.Xml.Linq; using System.Xml.XPath; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { this.Size = new System.Drawing.Size(600, 800); var tv = new TreeView { Parent = this, Dock = DockStyle.Fill }; var xe = XElement.Load("..\\..\\data.xml"); Fill(tv.Nodes, xe.XPathSelectElement("//Department[Parent_Dept_Code='00000000']")); tv.ExpandAll(); } void Fill(TreeNodeCollection nc, XElement xd) { Func<string, XElement> findTitle = code => xd.XPathSelectElement("//Title[Title_Code='" + code + "']"); var dc = xd.Element("Dept_Code").Value; var nn = nc.Add(xd.Element("Short_Name1").Value); var rels = from x in xd.XPathSelectElements("//Relation[Dept_Code1='" + dc + "']") let position = findTitle(x.XPathSelectElement("Titles_Codes/Title_Code2[1]").Value) let chief = findTitle(position.XPathSelectElement("Chief_Title_Codes/Title_Code1[1]").Value) select new { Person = x.XPathSelectElement("//Staff[Personal_Number='" + x.Element("Personal_Number1").Value + "']"), Position = position, Chief = chief }; var details = from x in rels select new { LastName = x.Person.Element("LName").Value, FirstName = string.Concat(x.Person.Element("FName").Value, " ", x.Person.Element("MName").Value), Title = x.Position.Element("Short_Name").Value, }; foreach (var x in details.GroupBy(d => d.Title)) { var tn = nn.Nodes.Add(x.Key); foreach (var p in x.OrderBy(n => n.LastName)) tn.Nodes.Add(p.LastName + " " + p.FirstName); } foreach (var s in xd.XPathSelectElements("//Department[Parent_Dept_Code='" + dc + "']")) Fill(nn.Nodes, s); } } }

