C# XML操作 代碼大全(讀XML,寫XML,更新,刪除節(jié)點(diǎn),與dataset結(jié)合等)第2/2頁(yè)
2005-10-3
一個(gè)通過(guò)DataSet操作XML的類
這段時(shí)間寫的項(xiàng)目每次都要用到XML保存一些配置,而每次操作XML都覺(jué)得挺麻煩,沒(méi)有數(shù)據(jù)庫(kù)那么順手。后來(lái)發(fā)現(xiàn)用DataSet操作XML很方便,而且靈活性比較好,于是寫了一個(gè)操作XML的類,用來(lái)應(yīng)付一般的XML操作(源碼下載附件)。
1 基本思路
其實(shí)用DataSet操作XML,歸根到底就是對(duì)DataSet里的表格,行,列等進(jìn)行操作,然后用DataSet里的東西重新寫到XML中,從而實(shí)現(xiàn)編輯XML的目的。如果再配合上.xsd文件的話,那效果更佳。
2 程序詳解
(1) XML文件內(nèi)容
本類操作的XML和生成的XML格式是一樣的,如下:
http://tempuri.org/xml_xmlDB.xsd">
2 Asp.net程序員
2
開(kāi)發(fā)B/S結(jié)構(gòu)程序
asp.net c#等
建國(guó)路XXX
2008-8-31
false
4
c#程序員
2
開(kāi)發(fā)B/S結(jié)構(gòu)程序
asp.net c#等
建國(guó)路XXX
2008-8-31
false
然后點(diǎn)擊XML文件右下角的“數(shù)據(jù)”,即可看到熟悉的表格形式,在表格的任意位置上單擊右鍵選擇“創(chuàng)建架構(gòu)”,將會(huì)生成一個(gè).xsd文件,該文件用來(lái)定義XML各列的類型。其內(nèi)容如下(點(diǎn)擊查看代碼2附件):
http://tempuri.org/xml_xmlDB.xsd" xmlns:mstns="http://tempuri.org/xml_xmlDB.xsd"xmlns="http://tempuri.org/xml_xmlDB.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"attributeFormDefault="qualified" elementFormDefault="qualified"> msdata:Locale="zh-CN" msdata:EnforceConstaints="False">?msdata:AutoIncrement="true" msdata:AutoIncrementStep="1"msdata:AutoIncrementSeed="1" />
注意:如果想像數(shù)據(jù)庫(kù)一樣有一個(gè)自動(dòng)增長(zhǎng)的ID字段,則可以這樣操作:
首先在XML中添加一個(gè)元素,這樣生成.xsd的時(shí)候,就會(huì)有一個(gè)ID段,在.xsd中選中ID這一列,在右邊的屬性中,將“AutoIncrementSeed”和“AutoIncrementStep”分別設(shè)置為1,這樣ID就會(huì)從1開(kāi)始以步長(zhǎng)為1自動(dòng)增長(zhǎng)。
以上代碼如果看不懂并不要緊,因?yàn)槲覀兛梢酝ㄟ^(guò)DataSet來(lái)生成這種格式的內(nèi)容。接下來(lái)將開(kāi)始操作XML。
(2) 處理XML文件路徑
這里主要是對(duì)傳入的XML路徑進(jìn)行處理,如果傳入的是相對(duì)路徑,則返回完整路徑,如果傳入的是完整路徑,則不做處理直接返回。方法如下:
#region GetXmlFullPath
///
/// 返回完整路徑
///
/// Xml的路徑
///
public static string GetXmlFullPath(string strPath)
{
//如果路徑中含有:符號(hào),則認(rèn)定為傳入的是完整路徑
if(strPath.IndexOf(":") > 0)
{
return strPath;
}
else
{
//返回完整路徑
return System.Web.HttpContext.Current.Server.MapPath(strPath);
}
}
#endregion
(3) 讀取記錄
讀取XML的數(shù)據(jù)到DataSet中的方法為:
#region GetDataSetByXml
///
/// 讀取xml直接返回DataSet
///
/// xml文件相對(duì)路徑
///
public static DataSet GetDataSetByXml(string strXmlPath)
{
try
{
DataSet ds = new DataSet();
//讀取XML到DataSet
ds.ReadXml(GetXmlFullPath(strXmlPath));
if(ds.Tables.Count > 0)
{
return ds;
}
return null;
}
catch(Exception)
{
return null;
}
}
#endregion
以上方法將得到一個(gè)DataSet,里面保存的是全部XML記錄的信息,而且沒(méi)有經(jīng)過(guò)任何處理。但很多時(shí)候我們需要的只是一些滿足條件的記錄,這時(shí)需要用以下方法得到:
#region GetDataViewByXml
/// 〈summary〉
/// 讀取Xml返回一個(gè)經(jīng)排序或篩選后的DataView
/// 〈/summary〉
/// 〈param name="strXmlPath"〉〈/param〉
/// 〈param name="strWhere"〉篩選條件,如:"name = 'kgdiwss'"〈/param〉
/// 〈param name="strSort"〉排序條件,如:"Id desc"〈/param〉
/// 〈returns〉〈/returns〉
public static DataView GetDataViewByXml(string strXmlPath,string strWhere,string strSort)
{
try
{
DataSet ds = new DataSet();
ds.ReadXml(GetXmlFullPath(strXmlPath));
//創(chuàng)建DataView來(lái)完成排序或篩選操作
DataView dv = new DataView(ds.Tables[0]);
if(strSort != null)
{
//對(duì)DataView中的記錄進(jìn)行排序
dv.Sort = strSort;
}
if(strWhere != null)
{
//對(duì)DataView中的記錄進(jìn)行篩選,找到我們想要的記錄
dv.RowFilter = strWhere;
}
return dv;
}
catch(Exception)
{
return null;
}
}
#endregion
(4) 插入記錄
到現(xiàn)在為止我們已經(jīng)可以隨意讀取XML中的記錄,接下來(lái)來(lái)實(shí)現(xiàn)寫入XML的操作,方法如下:
#region WriteXmlByDataSet
/// 〈summary〉
/// 向Xml文件插入一行數(shù)據(jù)
/// 〈/summary〉
/// 〈param name="strXmlPath"〉xml文件相對(duì)路徑〈/param〉
/// 〈param name="Columns"〉要插入行的列名數(shù)組,如:string[] Columns = {"name","IsMarried"};〈/param〉
/// 〈param name="ColumnValue"〉要插入行每列的值數(shù)組,如:string[] ColumnValue={"kgdiwss","false"};〈/param〉
/// 〈returns〉成功返回true,否則返回false〈/returns〉
public static bool WriteXmlByDataSet(string strXmlPath,string[] Columns,string[] ColumnValue)
{
try
{
//根據(jù)傳入的XML路徑得到.XSD的路徑,兩個(gè)文件放在同一個(gè)目錄下string strXsdPath = strXmlPath.Substring(0,strXmlPath.IndexOf(".")) + ".xsd";
DataSet ds = new DataSet();
//讀xml架構(gòu),關(guān)系到列的數(shù)據(jù)類型
ds.ReadXmlSchema(GetXmlFullPath(strXsdPath));
ds.ReadXml(GetXmlFullPath(strXmlPath));
DataTable dt = ds.Tables[0];
//在原來(lái)的表格基礎(chǔ)上創(chuàng)建新行
DataRow newRow = dt.NewRow();
//循環(huán)給 一行中的各個(gè)列賦值
for(int i=0; i〈 Columns.Length; i++)
{
newRow[Columns[i]] = ColumnValue[i];
}
dt.Rows.Add(newRow);
dt.AcceptChanges();
ds.AcceptChanges();
ds.WriteXml(GetXmlFullPath(strXmlPath));
return true;
}
catch(Exception)
{
return false;
}
}
#endregion
可能有的朋友不知道怎么用這個(gè)方法插入數(shù)據(jù),在后面我將用實(shí)例介紹。
(5) 修改記錄
修改記錄的方法要傳入的參數(shù)相對(duì)較多,因?yàn)樾薷挠涗浶枰榷ㄎ坏骄唧w哪一條記錄,再修改指定列的值,以下為修改XML的方法:
#region UpdateXmlRow
/// 〈summary〉
/// 更行符合條件的一條Xml記錄
/// 〈/summary〉
/// 〈param name="strXmlPath"〉XML文件路徑〈/param〉
/// 〈param name="Columns"〉列名數(shù)組〈/param〉
/// 〈param name="ColumnValue"〉列值數(shù)組〈/param〉
/// 〈param name="strWhereColumnName"〉條件列名〈/param〉
/// 〈param name="strWhereColumnValue"〉條件列值〈/param〉
/// 〈returns〉〈/returns〉
public static bool UpdateXmlRow(string strXmlPath,string[] Columns,string[] ColumnValue,string strWhereColumnName,string strWhereColumnValue)
{
try
{
//同上一方法
string strXsdPath = strXmlPath.Substring(0,strXmlPath.IndexOf(".")) + ".xsd";
DataSet ds = new DataSet();
//讀xml架構(gòu),關(guān)系到列的數(shù)據(jù)類型
ds.ReadXmlSchema(GetXmlFullPath(strXsdPath));
ds.ReadXml(GetXmlFullPath(strXmlPath));
//先判斷行數(shù)
if(ds.Tables[0].Rows.Count 〉 0)
{
for(int i=0; i〈 ds.Tables[0].Rows.Count; i++)
{
//如果當(dāng)前記錄為符合Where條件的記錄if(ds.Tables[0].Rows[i][strWhereColumnName].ToString().Trim().Equals(strWhereColumnValue))
{
//循環(huán)給找到行的各列賦新值
for(int j=0; j 〈 Columns.Length; j++)
{
ds.Tables[0].Rows[i][Columns[j]] = ColumnValue[j];
}
//更新DataSet
ds.AcceptChanges();
//重新寫入XML文件
ds.WriteXml(GetXmlFullPath(strXmlPath));
return true;
}
}
}
return false;
}
catch(Exception)
{
return false;
}
}
#endregion
(6) 刪除記錄
為了方便,刪除記錄提供了三個(gè)方法,一個(gè)可以刪除所有記錄,一個(gè)刪除符合條件的行,還有一個(gè)刪除指定Index值的行,該Index值和記錄在Data
Set中的Index值對(duì)應(yīng)。刪除所有記錄的方法為:
#region DeleteXmlAllRows
/// 〈summary〉
/// 刪除所有行
/// 〈/summary〉
/// 〈param name="strXmlPath"〉XML路徑〈/param〉
/// 〈returns〉〈/returns〉
public static bool DeleteXmlAllRows(string strXmlPath)
{
try
{
DataSet ds = new DataSet();
ds.ReadXml(GetXmlFullPath(strXmlPath));
//如果記錄條數(shù)大于0
if(ds.Tables[0].Rows.Count 〉 0)
{
//移除所有記錄
ds.Tables[0].Rows.Clear();
}
//重新寫入,這時(shí)XML文件中就只剩根節(jié)點(diǎn)了
ds.WriteXml(GetXmlFullPath(strXmlPath));
return true;
}
catch(Exception)
{
return false;
}
}
#endregion
刪除指定Index值的行的方法為:
#region DeleteXmlRowByIndex
/// 〈summary〉
/// 通過(guò)刪除DataSet中iDeleteRow這一行,然后重寫Xml以實(shí)現(xiàn)刪除指定行
/// 〈/summary〉
/// 〈param name="strXmlPath"〉〈/param〉
/// 〈param name="iDeleteRow"〉要?jiǎng)h除的行在DataSet中的Index值〈/param〉
public static bool DeleteXmlRowByIndex(string strXmlPath,int iDeleteRow)
{
try
{
DataSet ds = new DataSet();
ds.ReadXml(GetXmlFullPath(strXmlPath));
if(ds.Tables[0].Rows.Count 〉 0)
{
//刪除符號(hào)條件的行
ds.Tables[0].Rows[iDeleteRow].Delete();
}
ds.WriteXml(GetXmlFullPath(strXmlPath));
return true;
}
catch(Exception)
{
return false;
}
}
#endregion
這里說(shuō)一下提供此方法的原因,有的時(shí)候?qū)ML的內(nèi)容讀到DataSet,然后綁定到DataGrid后,由于DataGrid中只有一個(gè)模板列,而模板列里又套了表格等許多控件,這就使得我們可能無(wú)法得到記錄對(duì)應(yīng)的ID值,這個(gè)時(shí)候就可以先得到記錄的Index值(第一行為0,第二行為1,以此類推),然后將該Index值傳到方法中,就可以將該記錄刪掉。
注意:使用該方法的時(shí)候,綁定到DataGrid上的DataSet和刪除時(shí)用的DataSet要為同一個(gè),也就是說(shuō)Index要相同,不能有排序,不然會(huì)誤將記錄。
有時(shí)候我們需要?jiǎng)h除符合條件的多行,這個(gè)時(shí)候可以用以下方法實(shí)現(xiàn):
#region DeleteXmlRows
/// 〈summary〉
/// 刪除strColumn列中值為ColumnValue的行
/// 〈/summary〉
/// 〈param name="strXmlPath"〉xml相對(duì)路徑〈/param〉
/// 〈param name="strColumn"〉列名〈/param〉
/// 〈param name="ColumnValue"〉strColumn列中值為ColumnValue的行均會(huì)被刪除〈/param〉
/// 〈returns〉〈/returns〉
public static bool DeleteXmlRows(string strXmlPath,string strColumn,string[] ColumnValue)
{
try
{
DataSet ds = new DataSet();
ds.ReadXml(GetXmlFullPath(strXmlPath));
//先判斷行數(shù)
if(ds.Tables[0].Rows.Count 〉 0)
{
//判斷行多還是刪除的值多,多的for循環(huán)放在里面
if(ColumnValue.Length 〉 ds.Tables[0].Rows.Count)
{
for(int i=0; i 〈 ds.Tables[0].Rows.Count; i++)
{
for(int j=0; j 〈 ColumnValue.Length; j++)
{
//找到符合條件的行if(ds.Tables[0].Rows[i][strColumn].ToString().Trim().Equals(ColumnValue[j]))
{
//刪除行
ds.Tables[0].Rows[i].Delete();
}
}
}
}
else
{
for(int j=0; j 〈 ColumnValue.Length; j++)
{
for(int i=0; i 〈 ds.Tables[0].Rows.Count; i++)
{
//找到符合條件的行if(ds.Tables[0].Rows[i][strColumn].ToString().Trim().Equals(ColumnValue[j]))
{
//刪除行
ds.Tables[0].Rows[i].Delete();
}
}
}
}
ds.WriteXml(GetXmlFullPath(strXmlPath));
}
return true;
}
catch(Exception)
{
return false;
}
}
#endregion
3實(shí)例解析
(7) 讀取XML
以下代碼讀取到一個(gè)沒(méi)有排序和篩選的DataSet。
DataGrid1.DataSource = OperateXmlByDataSet.GetDataSetByXml(@"xml/xml_xmlDB.xml");
DataGrid1.DataBind();
以下代碼讀到的數(shù)據(jù)是經(jīng)過(guò)篩選和排序的:
DataGrid1.DataSource = OperateXmlByDataSet.GetDataViewByXml(
@"xml/xml_xmlDB.xml", //XML文件路徑
"name = 'Asp.net'", //條件:name列值為Asp.net
"peopleNum desc"); //按peopleNum列降序排列
DataGrid1.DataBind();
(8) 添加記錄
以下代碼向XML文件中添加了一條記錄,同時(shí)給7個(gè)列賦值:
bool b;
b = OperateXmlByDataSet.WriteXmlByDataSet(
@"xml/xml_xmlDB.xml", //XML文件地址
new string[]{
"name", //姓名字段
"peopleNum", //人數(shù)字段
"address", //地址字段
"description", //描述字段
"require", //需求字段
"deadLine", //結(jié)束時(shí)間字段
"IsMarried" //婚否字段
},
new string[]{
"Asp.net程序員", //姓名字段值
"2", //人數(shù)字段值
"建國(guó)路", //地址字段值
"B/S結(jié)構(gòu)程序", //描述字段值
"asp.net c#等", //需求字段值
DateTime.Now.ToShortDateString(), //結(jié)束時(shí)間字段值
"false" //婚否字段值
});
如果b返回值為true,表示添加成功,否則表示添加失敗。以上的寫法我用了些偷懶的方法,比如我把數(shù)組直接放在參數(shù),而沒(méi)有另外申明,事實(shí)上你可以另外申明一個(gè)數(shù)組,然后再傳到方法中。
請(qǐng)注意字段在數(shù)組中的位置和值在數(shù)組中的位置的對(duì)應(yīng)關(guān)系。
(9) 修改記錄
以下代碼將找到peopleNum列值為3的行,然后將行的name、peopleNum、、description和IsMarried四個(gè)字段的值分別更新成kgdiwss、10、描述、true。
bool b;
b = OperateXmlByDataSet.UpdateXmlRow(
@"xml/xml_xmlDB.xml",
new string[]{"name","peopleNum","description","IsMarried"},
new string[]{"kgdiwss","10","描述","true"},
"peopleNum",
"3");
返回true表示修改成功,否則表示修改失敗。
請(qǐng)?zhí)貏e注意,字段類型為邏輯型時(shí),賦值用的是true和false,而不是0和1。
(10) 刪除記錄
以下代碼實(shí)現(xiàn)刪除name列值為數(shù)組中的值的行。
bool b;
b = OperateXmlByDataSet.DeleteXmlRows(
@"xml/xml_xmlDB.xml", //XML文件路徑
"name", //條件列
new string[]{
"值1", //條件值1
"值2", //條件值2
"值3" //條件值3
});
上面代碼執(zhí)行成功后,name列值為值1、值2、值3的行將被刪除。
刪除成功返回true,否則返回false。
另外兩種刪除的方法用法比較簡(jiǎn)單,這里就不介紹了。
以上就是操作XML的所有方法,相信可以滿足很大一部份的使用了。然而,如果XML中的數(shù)據(jù)量比較大的話,使用以上方法效率可能不高,但話又說(shuō)回來(lái),如果數(shù)據(jù)量比較大的話,還是選擇數(shù)據(jù)庫(kù)比較好。
相關(guān)文章
ASP.Net Core基于EF6、Unitwork、Autofac實(shí)現(xiàn)Repository模式
這篇文章介紹了ASP.Net Core基于EF6、Unitwork、Autofac實(shí)現(xiàn)Repository模式的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02vscode extension插件開(kāi)發(fā)詳解
這篇文章主要介紹了vscode extension插件開(kāi)發(fā),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-05-05ASP.NET設(shè)計(jì)網(wǎng)絡(luò)硬盤之上傳文件實(shí)現(xiàn)代碼
用戶最終是要和文件打交道的,文件夾僅僅是用來(lái)方便管理的。文件的上傳和下載也就成為“網(wǎng)絡(luò)硬盤”功能設(shè)計(jì)中的重要一環(huán)2012-10-10WinForm中窗體間的數(shù)據(jù)傳遞交互的一些方法
通過(guò)子窗口向外引發(fā)一個(gè)事件,父窗口去實(shí)現(xiàn)該事件,我們可以再不關(guān)閉父窗口和子窗口的情況下進(jìn)行數(shù)據(jù)的傳輸顯示2012-12-12Hangfire在ASP.NET CORE中的簡(jiǎn)單實(shí)現(xiàn)方法
下面小編就為大家分享一篇Hangfire在ASP.NET CORE中的簡(jiǎn)單實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-11-11Asp.net(C#)實(shí)現(xiàn)驗(yàn)證碼功能代碼
asp.net驗(yàn)證碼的實(shí)現(xiàn)方法2008-10-10asp.net文件上傳功能(單文件,多文件,自定義生成縮略圖,水印)
上傳功能,是大家經(jīng)常用到了,可能每一個(gè)項(xiàng)目都可以會(huì)用到。網(wǎng)上到處都有上傳功能的代碼。比我寫的好的有很多。我這里也僅是分享我的代碼。2011-09-09ASP.NET如何定時(shí)調(diào)用WebService服務(wù)
在ASP.NET程序中,可以通過(guò)Time組件實(shí)現(xiàn)定時(shí)器功能,但是它與數(shù)據(jù)庫(kù)中的任務(wù)計(jì)劃不一樣,它必須基于程序正在運(yùn)行中才可生效,而數(shù)據(jù)庫(kù)任務(wù)計(jì)劃是不需要基于ASP.NET程序運(yùn)行而執(zhí)行任務(wù)。2015-10-10