2014-02-13 65 views
0

我試圖使用c#解析來自聯合國網站(http://www.un.org/sc/committees/1267/AQList.xml)的XML文件。解析C中的UN XML文件#

我經常用這個文件有一個問題,那就是從一個< .INDIVIDUAL。>標籤到另一個標籤的子標籤數量不同。一個例子是< .FORTH_NAME。>子標籤。

我試過了很多不同的方法,但不知何故,我似乎總是陷入同樣的​​問題,這是< .INDIVIDUAL。>標記中的不同數量的子標記。

我想要實現的是收集所有的標籤和它們的值在一個< .INDIVIDUAL。>標籤下,然後只插入我想要的數據到我的數據庫中。如果缺少一個標籤,例如< .FOURTH_NAME。>,那麼我只需要將前三個名稱插入數據庫中,並跳過第四個。

我使用LINQ to XML試過了,這裏有一些例子:

  XDocument xdoc = XDocument.Load(path); 

      var tags = (from t in xdoc.Descendants("INDIVIDUALS") 
         from a in t.Elements("INDIVIDUAL") 

         select new 
         { 
          Tag = a.Name, 
          val = a.Value 
         }); 

      foreach (var obj in tags) 
      { 
       Console.WriteLine(obj.Tag + " - " + obj.val + "\t"); 

//insert SQL goes here 
      } 

或:

但是這一次只收集非空FOURTH_NAME標籤...

  var q = (from c in xdoc.Descendants("INDIVIDUAL") 
        from _1 in c.Elements("FIRST_NAME") 
        from _2 in c.Elements("SECOND_NAME") 
        from _3 in c.Elements("THIRD_NAME") 
        from _4 in c.Elements("FOURTH_NAME") 

        where _1 != null && _2 != null && _3 != null && _4 != null 

        select new 
        { 
         _1 = c.Element("FIRST_NAME").Value, 
         _2 = c.Element("SECOND_NAME").Value, 
         _3 = c.Element("THIRD_NAME").Value, 
         _4 = c.Element("FOURTH_NAME").Value 
        }); 

      foreach (var obj in q) 
      { 
       Console.WriteLine("Person: " + obj._1 + " - " + obj._2 + " - " + obj._3 + " - " + obj._4); 
//insert SQL goes here 
      } 

任何想法??

回答

1

不要在元素上調用Value,而應考慮使用字符串強制類型轉換。如果元素不存在,LINQ to XML安全地返回null。請嘗試以下操作:

var data = XElement.Load(@"http://www.un.org/sc/committees/1267/AQList.xml"); 
var individuals = data.Descendants("INDIVIDUAL") 
    .Select(i => new { 
     First = (string)i.Element("FIRST_NAME"), 
     Middle = (string)i.Element("SECOND_NAME"), 
     Last = (string)i.Element("THIRD_NAME") 
    }); 

如果您想要更靈活並獲得所有名稱字段,可以執行下列操作。 (我會留下個人分組的過程中作爲一個額外的家庭作業;-)

data.Descendants("INDIVIDUAL").Elements() 
    .Where (i =>i.Name.LocalName.EndsWith("_NAME")) 
    .Select(i => new { FieldName= i.Name.LocalName, Value=i.Value}); 
+0

這是非常好的,樂於助人。有沒有一種方法可以動態讀取標籤,而不用硬編碼這些標籤:first_name,second等? – Alex

+1

當然,你可以使用像data.Descendants(「INDIVIDUAL」)。Elements()。這裏(i => i.Name.LocalName.EndsWith(「_ NAME」))。Select(i = > new {FieldName = i.Name.LocalName,Value = i.Value});'您可能想要爲每個人添加分組操作或子選擇。您可以根據您的業務需求來處理解析。看起來他們的數據需要一些標準化。某些情況下,您可能需要先分割多個名稱。 –

+0

謝謝吉姆,這是我所需要的...... – Alex

1

你爲什麼不使用XmlSerializer和LINQ呢?

正如this答案解釋,產生一個新的CS文件的類通過粘貼:

menu EDIT > Paste Special > Paste XML As Classes.

然後一樣容易抓住你的數據如下:

var serializer = new XmlSerializer(typeof (CONSOLIDATED_LIST)); 
using (FileStream fileStream = File.OpenRead(@"..\..\aqlist.xml")) 
{ 
    var list = serializer.Deserialize(fileStream) as CONSOLIDATED_LIST; 
    if (list != null) 
    { 
     var enumerable = list.INDIVIDUALS.Select(s => new 
     { 
      FirstName = s.FIRST_NAME, 
      SecondName = s.SECOND_NAME, 
      ThirdName = s.THIRD_NAME, 
      FourthName = s.FOURTH_NAME 
     }); 
    } 
} 

enter image description here

然後,您可以指定更適合您需求的謂詞。

走向這條道路將是一個巨大的節省時間和不易出錯,沒有必要使用字符串來訪問領域,強類型等等