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排除的话,那么递归出来的结果就不正确了。。。

 

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

 

你可能感兴趣的:(xml)