c#递归生成XML

本次内容:使用递归生成无限极XML

递归方法大家应该都很熟悉了,简而言之就是方法内部调用自己,就这样不断重复重复再重复的执行,

不过要担心死循环哟。。。

 

当我们系统需要动态生成菜单时,也就是说我们系统的菜单是存在数据库中的,数据库结构类似于:

 

ID,Name,Parent_ID 这种设计方法的时候,我们就需要根据ID 和 Parent_ID的关系来动态生成菜单。。

 

至于怎么生成菜单,今天就不介绍了,今天主要介绍的是 使用递归的方式来生成XML结构的文档。。

 

 

1 using System;
2  using System.Collections.Generic;
3  using System.Linq;
4  using System.Text;
5  using System.Data;
6  using System.Collections;
7 using System.Xml;
8
9 using NUnit.Framework;
10
11 namespace H.MySystem.Test
12 {
13 [TestFixture]
14 class MyTest
15 {
16 public DataTable InitTable()
17 {
18 DataTable dt = new DataTable();
19
20 dt.Columns.Add("ID",typeof(string));
21 dt.Columns.Add("Name", typeof(string));
22 dt.Columns.Add("Parent_ID", typeof(string));
23
24 DataRow row1 = dt.NewRow();
25 row1["ID"] = "1";
26 row1["Name"] = "第一个节点";
27
28 DataRow row11 = dt.NewRow();
29 row11["ID"] = "11";
30 row11["Name"] = "第4个节点";
31 row11["Parent_ID"] = "2";
32
33 DataRow row2 = dt.NewRow();
34 row2["ID"] = "2";
35 row2["Name"] = "第二个节点";
36 row2["Parent_ID"] = "1";
37
38 DataRow row3 = dt.NewRow();
39 row3["ID"] = "3";
40 row3["Name"] = "第3个节点";
41 row3["Parent_ID"] = "1";
42
43 dt.Rows.Add(row1);
44 dt.Rows.Add(row2);
45 dt.Rows.Add(row3);
46 dt.Rows.Add(row11);
47 return dt;
48 }
49 //最终XML文档
50 XmlDocument xd = new XmlDocument();
51 //已经使用过的节点ID
52 ArrayList usedElement = new ArrayList();
53
54 [Test]
55 public void TestBuild()
56 {
57 //初始化测试数据
58 DataTable dt = InitTable();
59
60 //新建一个根节点
61 XmlElement xe = xd.CreateElement("Datas");
62 xd.AppendChild(xe);
63
64 //执行递归,添加XML节点
65 BTest(dt, xe);
66
67 System.Console.WriteLine(xd.OuterXml);
68 Assert.AreNotEqual(0, dt.Rows.Count);
69 }
70
71 /// <summary>
72 /// 递归添加XML节点
73 /// </summary>
74 /// <param name="dt">数据源</param>
75 /// <param name="node">当前节点</param>
76 public void BTest(DataTable dt, XmlElement node)
77 {
78 XmlElement tmp;
79
80 var list = from r in dt.AsEnumerable()
81 select r;
82 if (node != null && node.Attributes["ID"] != null)
83 {
84 list = from r in dt.AsEnumerable()
85 where r["Parent_ID"].ToString().Equals(node.Attributes["ID"].Value)
86 select r;
87 }
88 foreach (var row in list)
89 {
90 if (!usedElement.Contains(row["ID"].ToString()))
91 {
92 usedElement.Add(row["ID"].ToString());
93 tmp = xd.CreateElement("Item");
94 tmp.SetAttribute("ID", row["ID"].ToString());
95 tmp.SetAttribute("Name", row["Name"].ToString());
96 tmp.SetAttribute("Parent_ID", row["Parent_ID"].ToString());
97
98 node.AppendChild(tmp);
99 //node = tmp;
100
101 BTest(dt, tmp);
102 }
103 }
104 }
105 }
106 }
107

 

 

 

 

 代码如上:

 

 主要思路就是每次执行 递归方法时,根据传入的当前XML节点,找到属于该节点的下一级节点(根据ID和Parent_ID查找)

这里还有一点需要注意的是我使用了一个集合(usedElement)来存放已经执行过、已经找到自己位置的ID,如果不把已经找到自己位置的ID排除的话,那么递归出来的结果就不正确了。。。

 

上面只测试了几条数据,不知道数据量大的情况下这种算法能否吃的消,呵呵。。

 

posted @ 2010-04-04 00:05  -Enchant  阅读(1903)  评论(0编辑  收藏  举报