2015-11-10 78 views
0

我有一個需要解析並加載到c#類中的xml字符串列表。我收到空引用異常,並認爲它的「根」原因是在xml中使用的命名空間。我不熟悉ling到xml,所以如果這個解決方案看起來不好,請提供替代方案。XML:XElement.Parse正在拋出異常

這裏的解析代碼:

XNamespace ns = "http://www.example.com/schema/msc/message"; 
XNamespace ns2 = "http://www.example.com/schema/msc/referral"; 

// data is List<string> 
Parallel.ForEach(data, item => 
{ 
    var root = XElement.Parse(item); 
    var dto = new DTO 
     { 
     RoutingCode = (string)root.Element("Message") 
       .Element(ns + "Params") 
       .Element(ns + "Events") 
       .Attribute("Code") 
     User = new UserDTO 
        { 
        AccountName = (string)root.Element("Message") 
            .Element("Params") 
            .Element("Events") 
            .Element("ref:User") 
            .Element("Name") 
        } 
     }; 
    list.Add(dto); 
}); 

下面是一個示例XML元素(減小尺寸的可讀性)

<Message xmlns="http://www.example.com/schema/msc/message"> 
    <Params> 
    <Events xmlns="http://www.example.com/schema/msc/referral" Code="AC"> 
     <ref:User xmlns:ref="http://www.example.com/schema/msc/referral" Name="asdf"/> 
    </Events> 
    </Parama> 
</Message> 

回答

1

這裏有幾件事情。

  1. 正如Martin Honnen指出的,您正在使用XElement.Parse。這意味着您的案例中的rootMessage並且不會有該名稱的子元素。
  2. 您正在正確使用名稱空間來獲取路由代碼,但是您忽略它們以填充UserDTO。名稱應該是,例如,ns + Paramsns2 + User
  3. 用戶的名字是屬性,而不是元素

我想提出的另一個建議是不要提前離開monad。使用返回IEnumerable<T>的方法,直到不必。所以更喜歡root.Elements(ns + "Params").Elements(ns + "Events").SingleOrDefault()root.Element(ns + "Params").Element(ns +"Events")。這避免了空引用異常。

把所有這些組合起來,我們得到這樣的:

XNamespace message = "http://www.example.com/schema/msc/message"; 
XNamespace referral = "http://www.example.com/schema/msc/referral"; 

var root = XElement.Parse(xml); 

var dto = new 
{ 
    RoutingCode = (string) root.Elements(message + "Params") 
     .Elements(referral + "Events") 
     .Attributes("Code") 
     .Single(), 
    User = new 
    { 
     AccountName = (string) root.Elements(message + "Params") 
      .Elements(referral + "Events") 
      .Elements(referral + "User") 
      .Attributes("Name") 
      .Single() 
    } 
}; 

的工作示例見this fiddle

1

如果使用XElement.Parse而不是XDocument.Parse那麼你root元素是Message元素任何選擇的孩子都應該從Params元素開始。

 RoutingCode = (string)root.Element(ns + "Params") 
      .Element(ns2 + "Events") 
      .Attribute("Code") 
+0

這是有道理的,但我仍然得到例外。任何方式我可以更好地獲取調試信息,而不是捕獲異常? –

0

試試這個代碼來檢索屬性。

var doc = XDocument.Parse(xml); 

XNamespace ns = "http://www.example.com/schema/msc/referral"; 

doc.Descendants(ns + "Events") 
    .Select(e => new DTO { 
          RoutingCode = (string)e.Attribute("Code"), 
          User = new UserDTO((string)e.Element(ns + "User").Attribute("Name")) 
        }); 
0

嘗試命名空間鏈接到的XElement

using System; 
 
using System.Collections.Generic; 
 
using System.Linq; 
 
using System.Text; 
 
using System.Xml; 
 
using System.Xml.Linq; 
 

 
namespace ConsoleApplication1 
 
{ 
 
    class Program 
 
    { 
 
     static void Main(string[] args) 
 
     { 
 
      string item = 
 
       "<Message xmlns=\"http://www.example.com/schema/msc/message\">" + 
 
        "<Params>" + 
 
        "<Events xmlns=\"http://www.example.com/schema/msc/referral\" Code=\"AC\">" + 
 
         "<ref:User xmlns:ref=\"http://www.example.com/schema/msc/referral\" Name=\"asdf\"/>" + 
 
        "</Events>" + 
 
        "</Params>" + 
 
       "</Message>"; 
 

 
      XElement root = XElement.Parse(item); 
 
      XNamespace ns1 = root.Name.Namespace; 
 
      XNamespace ns2 = root.Descendants().Where(x => x.Name.LocalName == "Events").FirstOrDefault().Name.Namespace; 
 

 
     } 
 
    } 
 
}​