Linq to Xml讀取複雜xml(帶命名空間)

前言:xml的操做方式有多種,但要論使用頻繁程度,博主用得最多的仍是Linq to xml的方式,以爲它使用起來很方便,就用那麼幾個方法就能完成簡單xml的讀寫。以前作的一個項目有一個很變態的需求:C#項目調用不知道是什麼語言寫的一個WebService,而後添加服務引用老是失敗,經過代理的方式動態調用也老是報錯,最後沒辦法,經過發送原始的WebRequest請求直接獲得對方返回的一個xml文件。注意過webservice的wsdl文件的朋友應該知道這個是系統生成的xml文件,有點複雜,研究了半天終於能正常讀寫了。今天在這裏和你們分享下。web

 

一、介紹以前,首先回顧下Linq to xml的方式讀寫簡單xml的方法服務器

(1)讀取xmlide

<?xml version="1.0" encoding="utf-8"?>

<BizADsList>

  <adData aid="1" image="baidu.jpg" link="www.baidu.com" title="百度"/>

  <adData aid="2" image="qq.jpg" link="www.qq.com" title="騰訊"/>

</BizADsList>
var strPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"data\test.xml");
            XDocument adList = XDocument.Load(strPath);

            var ad = from a in adList.Descendants("BizADsList").Elements("adData")

                     select new

                     {

                         image = a.Attribute("image").Value,

                         link = a.Attribute("link").Value,

                         title = a.Attribute("title").Value

                     };

            string s = "";

            foreach (var a in ad)

                s += a.image;

(2)寫xmlspa

        /// <summary>
        /// 根據獲得的Document集合生成XML
        /// </summary>
        /// <param name="lstDocumentBD"></param>
        /// <param name="docNE"></param>
        /// <param name="strSpiderTime"></param>
        /// <param name="strNewRate"></param>
        private static void SaveXmlByLstDocument(List<Document> lstDocumentBD, Document docNE, string strSpiderTime, string strNewRate)
        {
            try
            {
                XDocument xDoc = new XDocument();
                XElement xRoot = new XElement(CSpiderConst.XML_ELE_ROOT);

                //1.構造Device節點
                XElement xDevice = new XElement(CSpiderConst.XML_ELE_DEVICE);

                //2.構造NE節點
                XElement xNE = new XElement(CSpiderConst.XML_ELE_NE);
                foreach (var oDocNE in docNE)
                {
                    XElement xItem = new XElement(CSpiderConst.XML_ELE_ITEM, new XAttribute(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 (var oDocument in lstDocumentBD)
                {
                    XElement xBD = new XElement(CSpiderConst.XML_ELE_BD);
                    foreach (var oDocBD in oDocument)
                    {
                        XElement xItem = new XElement(CSpiderConst.XML_ELE_ITEM, new XAttribute(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來命名
                var strDirectoryPath = 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文件的操做。代理

 

二、進入今天的正題:讀寫帶命名空間的xml文件。code

首先來看一段xmlxml

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

第一次看到這個文件確實讓人萌神了,好比須要取一個msdata:IsDataSet="true"這個屬性,該怎麼取...對象

解析以前,先來分析下這段xml,<DataSet xmlns="http://WebXml.com.cn/">這段裏面有一個xmlns屬性,這個屬性是每個標籤自帶的屬性,不信你能夠新建一個xml文件,而後在任何一個標籤裏面輸入xmlns屬性,後面都會出來不少的系統自帶的命名空間。這個屬性表示所屬標籤在哪一個命名空間下面,因此在取的時候要帶上這個命名空間。blog

先來看看解析的代碼:utf-8

var strPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"data\test.xml");
var oRoot = XDocument.Load(strPath);
//取DataSet標籤
var oDataSet = oRoot.Element(XName.Get("DataSet", "http://WebXml.com.cn/"));
//取schema標籤
var oSchema = oDataSet.Element(XName.Get("schema", "http://www.w3.org/2001/XMLSchema"));
//取element標籤
var oElement = oSchema.Element(XName.Get("element", "http://www.w3.org/2001/XMLSchema"));//這兩個節點都是以xs打頭,因此命名空間都是xs的命名空間
//取element標籤下面的IsDataSet屬性
var oElementValue = oElement.Attribute(XName.Get("IsDataSet", "urn:schemas-microsoft-com:xml-msdata"));
//取aa標籤
var oAA = oSchema.Element(XName.Get("aa", "urn:schemas-microsoft-com:xml-msdata"));

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

(1)咱們來解析下

<xs:schema xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="getRegion">

這一句,最前面的"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標籤

 <msdata:aa>
      test
 </msdata:aa>

msdata就是上面schema標籤裏面定義的另外一個命名空間,表示aa標籤屬於msdata命名空間下面。

(3)再看來看屬性的取法:

<xs:element name="getRegion" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">

若是要取msdata:IsDataSet="true",因爲這個屬性也帶有命名空間,因此取屬性時也要加上命名空間了。因此須要這樣取。

var oElementValue = oElement.Attribute(XName.Get("IsDataSet", "urn:schemas-microsoft-com:xml-msdata"));

 

      如今大夥們應該對這種xml有一個更加清晰的認識了吧。其實通常狀況下這種場景比較少見,由於這麼複雜的xml通常是由引用服務時代理對象去解析的。但若是真的有這麼變態的需求咱們也不用擔憂了。在此記錄下,之後若是你們遇到但願能節約大夥的時間。

相關文章
相關標籤/搜索