关于网站应用中XML的使用心得[原创]
2007-10-06 11:32 Brush 阅读(5019) 评论(23) 收藏 举报 最近忙于做一个小网站,是电子商务性质的。其中很多地方我用到了XML文件作为数据存储的方式,目的就是减轻数据库负担。
经过一两个月,在XML数据操作这块也有了一定经验,现在把它写出来共享给大家,同时也欢迎大家参与讨论。
(注:本文虽然质量不高,但转载望注明一下出处,谢谢合作!)
1。如果数据库表的记录是分组的,总的操作频繁但每组的并不频繁,且数据对保密性要求不高。那可以用XML。
如论坛的回帖,因为如果用数据库,好多回帖都添加到一张表里,数据库并发的可能性就大了,但换成XML,每个帖子专门建立一个文件夹,回帖里的内容均用XML文件来保存,这样的话,并发性就得到了很好的控制。
2。数据库量大的,如果用XML保存,在存取上会比较慢。所以如果能分成若干个XML文件保存就比较好。
如回帖,每50个回帖建立一个新的XML文件,而且名字跟页数对应,这样也能简化翻页。更大地减少了并发操作。
3。能用XSD描述数据结构的,就尽量描述。(开始是写的XSLT,后来更正)
这样对查询数据(当使用DataSet查询时)时,尤其是在数据量大的时候,能获得相当大的速度提升(它跳过了DataSet的自动分析XML结构的步骤)。
4。查询XML数据,尽量使用XML空间下提供的类。
这样能对XML进行快速地高效率地读写操作。 (稍后我会把自己写的XML操作类帖出来,供大家参考)
5。使用XML时,要注意结点的值。
有的值是需要过滤掉的,因为查询XML数据要用到XPath,其语法中的关键字是不能出现在查询关键字里的。
6。能用结点,就不要使用属性。尽量构架规范的XML结构。
比如说相册:
<root >
<相册 >
<名称/ >
<创建时间 / >
<相片 >
<图 >
<图名/ >
<地址/ >
<上传时间/ >
</图 >
</相片 >
</相册 >
</root >
在这个结构中,每个图要这样放在相片结点下,而不要直接放在root结点下。这样有助于XSD(原为XSLT,后更正)结构的清晰。程序读取数据也方便。
另,如果属性使用太多,对XPath查询会有影响,一些查询就可能不容易实现。
其实使用XML作为数据存储方式还有好多优点,比如RSS订阅,客户端解析成HTML页面等。
以上仅是个人的一点经验之谈,不足不馁不对之处,望各高手不吝赐教。
后来加的:
这里我看重的是数据的分别保存分别处理的思想。利用XML文件的分开存放使无相关的数据不再像数据库的表那样会互相影响。
大家以考虑下,如果回帖用表来保存,这样,不管你回复哪个帖子,都要在这张表中插入一条新记录,此时的并发显然是比较高。高的原因是,不相关的回帖,即回复不同的帖子,在这种情况下也相互影响、限制了。
如果回帖换成使用XML保存,每个帖子的回复只使用一个XML(当然为了分页方便,可以每N个回复建立一个文件,这样也省了分页查询了)。此时的并发,就被分解了。分解到回复一个帖子的情况。并且,在写XML文件时候,加上写保护,独占此资源,写完释放(而读取回帖不受影响)。这样,除非瞬间有许多人在回复同一帖子,才会形成比较大的并发操作(此时还能产生这样的并发量的网站实在是够大的了)。
网站中的个人消息,操作记录等,我觉得,均比较适合用XML作数据源。而且是很理想的。
下面是我在项目中自己写的XML操作类。
1
using System;2
using System.Xml;3
using System.Data;4
using System.Collections;5

6
namespace lib.xml7


{8
public class XmlControl 9

{10

11

=== 保护成员 ===#region === 保护成员 ===12
13
protected string _strXmlFile; // XML文件的路径14
protected XmlDocument _objXmlDoc = new XmlDocument(); // XML文件15

16
#endregion17

18

19

=== 构造函数 ===#region === 构造函数 ===20

21

/**//// <summary>22
/// 23
/// </summary>24
/// <param name="xmlFilePath">文件路径(服务器的绝对路径)</param>25
public XmlControl(string xmlFilePath) 26

{ 27
try 28

{29
_objXmlDoc.Load(xmlFilePath);30
}31
catch (System.Exception ex) 32

{33
throw ex; 34
}35
_strXmlFile = xmlFilePath; 36
}37

38
#endregion39

40

41

=== 查看是否存在 ===#region === 查看是否存在 ===42
public bool IsExist(string xpath)43

{44
XmlNode xn = this._objXmlDoc.SelectSingleNode(xpath);45
return xn == null? false: true;46
}47
#endregion48

49

50

=== 统计结点数目 ===#region === 统计结点数目 ===51

/**//// <summary>52
/// 获取结果个数53
/// </summary>54
public int GetCount(string xpath)55

{56
XmlNodeList xnl = _objXmlDoc.SelectNodes(xpath);57
return xnl == null ? 0 : xnl.Count;58
}59
#endregion60

61

62

=== 查询数据 ===#region === 查询数据 ===63

64

-- 根据Xpath查询 --#region -- 根据Xpath查询 --65

/**//// <summary>66
/// 查找对应结点的数据67
/// </summary>68
/// <param name="xPaht">结点选择</param>69
public DataView GetData(string xPath) 70

{ 71
DataSet ds = GetDataSet(xPath); 72
// XmlReader read = new XmlNodeReader(_objXmlDoc.SelectSingleNode(xPath)); 73
// ds.ReadXml(read); 74
return ds.Tables.Count == 0 ? null : ds.Tables[0].DefaultView; // 防止空结果75
}76

77

/**//// <summary>78
/// 获取某个结点下面的所有子元素对应的hashtable79
/// </summary>80
/// <param name="xpath"></param>81
/// <returns></returns>82
public Hashtable GetElemet(string xpath)83

{84
Hashtable hs = new Hashtable();85
XmlNode xn = _objXmlDoc.SelectSingleNode(xpath);86
if(xn != null)87

{88
foreach(XmlNode x in xn.ChildNodes)89

{90
hs.Add(x.Name, x.InnerText);91
}92
}93

94
return hs;95
}96

97

/**//// <summary>98
/// 获取某个元素的列表99
/// </summary>100
/// <param name="xpath"></param>101
/// <returns></returns>102
public IList GetElemetList(string xpath)103

{104
IList list = new ArrayList();105
XmlNodeList xnl = _objXmlDoc.SelectNodes(xpath);106
if(xnl != null)107

{108
foreach(XmlNode x in xnl)109

{110
list.Add(x.InnerText);111
}112
}113
return list;114
}115

116

/**//// <summary>117
/// 获取单个结点里面内容118
/// </summary>119
/// <param name="xpath"></param>120
/// <returns>无则返回null</returns>121
public string GetSingleNode(string xpath)122

{123
XmlNode xn = _objXmlDoc.SelectSingleNode(xpath);124
if(xn != null)125

{126
return xn.InnerText;127
}128
return null;129
}130
#endregion131

132

-- 获取对应DataSet --#region -- 获取对应DataSet --133
// 只能获取列相等的记录134
private DataSet GetDataSet(string xPath)135

{136
XmlNodeList xnl = _objXmlDoc.SelectNodes(xPath);137
// XmlTextReader reader = new XmlTextReader(138
XmlDocument xd = new XmlDocument();139
XmlNode rootNode = xd.CreateNode(XmlNodeType.Element, "root", null);140
141
DataSet ds = new DataSet();142
for(int i=0; i<xnl.Count; i++)143

{144
// read = new XmlNodeReader(xnl.Item(i));145
rootNode.AppendChild(xd.ImportNode(xnl.Item(i), true));146
// if(i == 0) // 初始化DS147
// {148
// ds.ReadXml(read);149
// }150
// else // 为DS的表添加行151
// {152
// DataSet dss = new DataSet();153
// dss.ReadXml(read);154
// ds.Tables[0].Rows.Add(dss.Tables[0].Rows[0].ItemArray);155
// }156
}157
XmlNodeReader reader = new XmlNodeReader(rootNode);158
ds.ReadXml(reader);159
return ds;160
}161
#endregion162

163
#endregion164

165

166

=== 更新结点/元素 ===#region === 更新结点/元素 ===167

168

/**//// <summary>169
/// 更新一元素170
/// </summary>171
/// <param name="elementPath">结点地址</param>172
/// <param name="content">值</param>173
public bool UpdateElement(string elementPath, string content) 174

{175
XmlNode xn = _objXmlDoc.SelectSingleNode(elementPath);176
if(xn == null)177
return false;178
xn.InnerText = content;179
return true;180
}181

182

/**//// <summary>183
/// 更新某一结点下的指定元素值184
/// </summary>185
/// <param name="nodePath">目标结点</param>186
/// <param name="elements">元素名称</param>187
/// <param name="cotents">元素新值</param>188
public bool UpdateElements(string nodePath, string[] elements, string[] contents)189

{190
XmlNode objNode = _objXmlDoc.SelectSingleNode(nodePath); // 找到目标结点191
192
if(objNode == null)193
return false;194

195
// 更新目标结点的元素196
for(int i = 0; i < elements.Length; i++)197

{198
objNode.SelectSingleNode(elements[i]).InnerText = contents[i];199
}200

201
return true;202
}203

204
#endregion205

206

207

=== 删除结点/元素 ===#region === 删除结点/元素 ===208

209

/**//// <summary>210
/// 删除一结点(包括子结点)211
/// </summary>212
/// <param name="nodePath">目标结点</param>213
public bool DeleteNode(string nodePath)214

{215
try216

{217
XmlNode aimNode = _objXmlDoc.SelectSingleNode(nodePath); // 目标结点218
if(aimNode != null)219

{220
aimNode.ParentNode.RemoveChild(aimNode); // 删除221
}222
return true;223
}224
catch225

{226
return false;227
}228
}229

230

/**//// <summary>231
/// 删除符合条件的所有结点232
/// </summary>233
/// <param name="xPath">条件</param>234
public bool DeleteNodes(string xPath)235

{236
XmlNodeList listNode = _objXmlDoc.SelectNodes(xPath);237
if(listNode == null)238
return true;239
try240

{241
foreach(XmlNode aimNode in listNode)242

{243
aimNode.ParentNode.RemoveChild(aimNode);244
}245
return true;246
}247
catch248

{249
return false;250
}251
}252

253
#endregion254

255

256

=== 插入结点/元素 ===#region === 插入结点/元素 ===257

258

/**//// <summary>259
/// 插入一节点和其所有元素260
/// </summary>261
/// <param name="MainNode">父节点,目标位置</param>262
/// <param name="ChildNodes">新的结点</param>263
/// <param name="Element">新的元素名称</param>264
/// <param name="Content">元素内容</param>265
public bool InsertNodeWithElements(string MainNode, string ChildNode, string[] Elements, string[] Contents) 266

{267
return InsertNodeWithElements(MainNode, ChildNode, Elements, Contents, true);268
}269

270
public bool InsertNodeWithElements(string MainNode, string ChildNode, string[] Elements, string[] Contents, bool isLast) 271

{272
XmlNode objRootNode = _objXmlDoc.SelectSingleNode(MainNode); // 找到父节点,即目标位置273

274
if(objRootNode != null)275

{276
XmlElement objChildNode = _objXmlDoc.CreateElement(ChildNode); // 新建结点277
if(isLast)278

{279
objRootNode.AppendChild(objChildNode); // 添加到父结点末尾280
}281
else282

{283
objRootNode.PrependChild(objChildNode); // 添加到父结点开头284
}285

286
// 添加所有元素及内容到新加结点中287
for(int i=0; i<Elements.Length; i++)288

{289
XmlElement objElement = _objXmlDoc.CreateElement(Elements[i]); 290
objElement.InnerText = Contents[i]; 291
objChildNode.AppendChild(objElement);292
}293
return true;294
}295
return false;296
}297
298

299

/**//// <summary>300
/// 在一位置插入多个元素301
/// </summary>302
/// <param name="MainNode">目标位置</param>303
/// <param name="Elements">元素名</param>304
/// <param name="Contents">内容</param>305
public bool InsertElements(string MainNode, string[] Elements, string[] Contents)306

{ 307
XmlNode objNode = _objXmlDoc.SelectSingleNode(MainNode); // 找到目标位置308

309
if(objNode != null)310

{311
// 添加所有元素和对应内容312
for(int i = 0; i<Elements.Length; i++)313

{314
XmlElement objElement = _objXmlDoc.CreateElement(Elements[i]);315
objElement.InnerText = Contents[i]; 316
objNode.AppendChild(objElement); 317
}318
return true;319
}320
return false;321
}322
#endregion323

324

=== 保存 ===#region === 保存 ===325

326
public bool Save() 327

{328
bool re = false;329
try 330

{ 331
_objXmlDoc.Save(_strXmlFile);332
re = true;333
} 334
catch (System.Exception ex) 335

{ 336
re = false;337
throw ex;338
}339
finally340

{341
_objXmlDoc = null;342
}343
return re;344
}345

346
#endregion347

348
} 349

350
}351

浙公网安备 33010602011771号