1. 程式人生 > >C#基礎系列:Linq to Xml讀寫xml

C#基礎系列:Linq to Xml讀寫xml

前言:xml的操作方式有多種,但要論使用頻繁程度,博主用得最多的還是Linq to xml的方式,覺得它使用起來很方便,就用那麼幾個方法就能完成簡單xml的讀寫。之前做的一個專案有一個很變態的需求:C#專案呼叫不知道是什麼語言寫的一個WebService,然後新增服務引用總是失敗,通過代理的方式動態呼叫也總是報錯,最後沒辦法,通過傳送原始的WebRequest請求直接得到對方返回的一個xml檔案。注意過webservice的wsdl檔案的朋友應該知道這個是系統生成的xml檔案,有點複雜,研究了半天終於能正常讀寫了。今天在這裡和大家分享下。

1、介紹之前,首先回顧下Linq to xml的方式讀寫簡單xml的方法

(1)讀取xml

12345 <?xml version="1.0"encoding="utf-8"?><BizADsList><adData aid="1"image="baidu.jpg"link="www.baidu.com"title="百度&quot
;/><adData aid="2"image="qq.jpg"link="www.qq.com"title="騰訊"/></BizADsList>
C#
123456789101112 varstrPath=Path.Combine(AppDomain.CurrentDomain.BaseDirectory,@"data\test.xml");XDocument adList=XDocument.Load(strPath);varad=fromainadList.Descendants("BizADsList").Elements("adData")selectnew{image=a.Attribute("image").Value,link=a.Attribute("link").Value,title=a.Attribute("title").Value};strings="";foreach(varainad)s+=a.image;

(2)寫xml

C#
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253 /// <summary>/// 根據得到的Document集合生成XML/// </summary>/// <param name="lstDocumentBD"></param>/// <param name="docNE"></param>/// <param name="strSpiderTime"></param>/// <param name="strNewRate"></param>privatestaticvoidSaveXmlByLstDocument(List<Document>lstDocumentBD,Document docNE,stringstrSpiderTime,stringstrNewRate){try{XDocument xDoc=newXDocument();XElement xRoot=newXElement(CSpiderConst.XML_ELE_ROOT);//1.構造Device節點XElement xDevice=newXElement(CSpiderConst.XML_ELE_DEVICE);//2.構造NE節點XElement xNE=newXElement(CSpiderConst.XML_ELE_NE);foreach(varoDocNE indocNE){XElement xItem=newXElement(CSpiderConst.XML_ELE_ITEM,newXAttribute(CSpiderConst.XML_PROP_NAME,oDocNE.Key),oDocNE.Value);xNE.Add(xItem);}//這裡增加一個<Item name='NewRate'>和<Item name='SpiderTimeEx'>節點用來儲存當前這次的利用率和當次的採集時間AddNewRateAndSpiderTime(strSpiderTime,strNewRate,xNE);xDevice.Add(xNE);//3.迴圈構造BD節點並新增到Device節點中foreach(varoDocument inlstDocumentBD){XElement xBD=newXElement(CSpiderConst.XML_ELE_BD);foreach(varoDocBD inoDocument){XElement xItem=newXElement(CSpiderConst.XML_ELE_ITEM,newXAttribute(CSpiderConst.XML_PROP_NAME,oDocBD.Key),oDocBD.Value);xBD.Add(xItem);}AddNewRateAndSpiderTime(strSpiderTime,strNewRate,xBD);xDevice.Add(xBD);}xRoot.Add(xDevice);xDoc.Add(xRoot);//4.儲存到採集器本地,以伺服器的時間和網元的AssetID來命名varstrDirectoryPath=Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"ReportFailed\\");if(!Directory.Exists(strDirectoryPath)){Directory.CreateDirectory(strDirectoryPath);}xDoc.Save(strDirectoryPath+docNE[TBLDeviceLCBB.PROP_ASSETID]+"_"+strSpiderTime.Replace(":","_")+".xml");}catch{CLogService.Instance.Debug("儲存XML失敗");}}

通過XDocument、XElement物件和Element()、Elements()兩個方法能完成大部分xml檔案的操作。

2、進入今天的正題:讀寫帶名稱空間的xml檔案。

首先來看一段xml

12345678910111213141516 &lt;?xml version=&quot;1.0&quot;encoding=&quot;utf-8&quot;?&gt;&lt;DataSet xmlns=&quot;http://WebXml.com.cn/&quot;&gt;&lt;xs:schema xmlns=&quot;&quot;xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot; xmlns:msdata=&quot;urn:schemas-microsoft-com:xml-msdata&quot; id=&quot;getRegion&quot;&gt;&lt;msdata:aa&gt;test&lt;/msdata:aa&gt;&lt;xs:element name=&quot;getRegion&quot;msdata:IsDataSet=&quot;true&quot;msdata:UseCurrentLocale=&quot;true&quot;&gt;&lt;xs:element name=&quot;Province&quot;&gt;&lt;xs:sequence&gt;&lt;xs:element name=&quot;RegionID&quot;type=&quot;xs:string&quot;minOccurs=&quot;0&quot;/&gt;&lt;xs:element name=&quot;RegionName&quot;type=&quot;xs:string&quot;minOccurs=&quot;0&quot;/&gt;&lt;/xs:sequence&gt;&lt;/xs:element&gt;&lt;/xs:element&gt;&lt;/xs:schema&gt;&lt;/DataSet&gt;

第一次看到這個檔案確實讓人萌神了,比如需要取一個msdata:IsDataSet=”true”這個屬性,該怎麼取…

解析之前,先來分析下這段xml,<DataSet xmlns=”http://WebXml.com.cn/”>這段裡面有一個xmlns屬性,這個屬性是每一個標籤自帶的屬性,不信你可以新建一個xml檔案,然後在任何一個標籤裡面輸入xmlns屬性,後面都會出來很多的系統自帶的名稱空間。這個屬性表示所屬標籤在哪個名稱空間下面,所以在取的時候要帶上這個名稱空間。

先來看看解析的程式碼:

C#
123456789101112 varstrPath=Path.Combine(AppDomain.CurrentDomain.BaseDirectory,@"data\test.xml");varoRoot=XDocument.Load(strPath);//取DataSet標籤varoDataSet=oRoot.Element(XName.Get("DataSet","http://WebXml.com.cn/"));//取schema標籤varoSchema=oDataSet.Element(XName.Get("schema","http://www.w3.org/2001/XMLSchema"));//取element標籤varoElement=oSchema.Element(XName.Get("element","http://www.w3.org/2001/XMLSchema"));//這兩個節點都是以xs打頭,所以名稱空間都是xs的名稱空間//取element標籤下面的IsDataSet屬性varoElementValue=oElement.Attribute(XName.Get("IsDataSet","urn:schemas-microsoft-com:xml-msdata"));//取aa標籤varoAA=oSchema.Element(XName.Get("aa","urn:schemas-microsoft-com:xml-msdata"));

我們來解析下幾個關鍵的地方:

(1)我們來解析下

1 &lt;xs:schema xmlns=&quot;&quot;xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot; xmlns:msdata=&quot;urn:schemas-microsoft-com:xml-msdata&quot; id=&quot;getRegion&quot;&gt;

這一句,最前面的”xs”表示標籤所屬名稱空間的變數,xmlns:xs=”http://www.w3.org/2001/XMLSchema”這個表示xs這個名稱空間的值。所以要得到schema這個標籤需要帶上名稱空間var oSchema = oDataSet.Element(XName.Get(“schema”, “http://www.w3.org/2001/XMLSchema”));這個標籤還定義了另一個名稱空間xmlns:msdata=”urn:schemas-microsoft-com:xml-msdata”。

(2)再來看看aa標籤

<