XML:XElement.Parse正在抛出异常

时间:2015-11-10 18:47:45

标签: c# xml linq-to-xml

我有一个xml字符串列表,我需要解析并加载到c#类中。我得到空引用异常,并认为它的“根”原因是xml中使用的命名空间。我不太熟悉xml,所以如果这个解决方案看起来不好,请提供替代方案。

这是解析代码:

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>

4 个答案:

答案 0 :(得分:1)

如果您使用的是XElement.Parse而不是XDocument.Parse,那么您的root元素就是Message元素,任何选择的子元素都应该以{{1​​}}元素开头。

Params

答案 1 :(得分:1)

这里有一些事情。

  1. 正如Martin Honnen所指出的那样,你正在使用XElement.Parse。这意味着您案例中的root Message,并且不会有该名称的子元素。
  2. 您正在使用名称空间来获取路由代码,但您忽略它们以填充UserDTO。例如,名称应为ns + Paramsns2 + User
  3. 用户的名称是属性,而不是元素
  4. 我要做的另一个建议是不要离开monad&#39;早。使用返回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

答案 2 :(得分:0)

尝试使用此代码检索属性。

pfnGetConnectedDevices myCallback = new pfnGetConnectedDevices() {
    public int apply(int dwDevice, IntByReference pdwCount) {
        // your code here
    }
};
lib.myFunction(myCallback);

答案 3 :(得分:0)

尝试将命名空间链接到XElement

&#13;
&#13;
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;

        }
    }
}​
&#13;
&#13;
&#13;