以下是我班级的完整代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml.Linq;
namespace SharpDIC.Entities
{
/// <summary>
/// Represents a forum on the Dream.In.Code website.
/// </summary>
public class Forum
{
//Forum information is given by this XML call:
//http://www.dreamincode.net/forums/xml.php?showforum=NUMBER_GOES_HERE
public string Name { get; set; }
public string ID { get; set; }
public string URL { get; set; }
public List<Subforum> Subforums { get; set; }
/// <summary>
/// Load a forum by providing an ID.
/// </summary>
/// <param name="id">A forum's individual ID number.</param>
public Forum(string ID)
{
WebClient webClient = new WebClient();
string htmlSource = webClient.DownloadString(new Uri(String.Format("http://www.dreamincode.net/forums/xml.php?showforum={0}", ID)));
XDocument xml = XDocument.Parse(htmlSource);
var forumXML = xml.Element("ipb").Element("forum");
//Load general profile information.
this.Name = forumXML.Element("name").Value;
this.ID = forumXML.Element("id").Value;
this.URL= forumXML.Element("url").Value;
//Load subforums.
var subforumsXML = xml.Element("ipb").Element("forum").Element("subforums");
this.Subforums = (from forum in subforumsXML.Descendants("forum")
select new Subforum()
{
ID = forum.Element("id").Value,
Name = forum.Element("name").Value,
URL = forum.Element("url").Value,
Description = forum.Element("description").Value,
Type = forum.Element("type").Value,
TopicCount = forum.Element("topics").Value,
ReplyCount = forum.Element("replies").Value,
LastPost = new LastPost()
{
Date = forum.Element("lastpost").Element("date").Value,
Name = forum.Element("lastpost").Element("name").Value,
ID = forum.Element("lastpost").Element("id").Value,
URL = forum.Element("lastpost").Element("url").Value,
UserWhoPosted = new Friend()
{
ID = forum.Element("lastpost").Element("user").Element("id").Value,
Name = forum.Element("lastpost").Element("user").Element("name").Value,
Url = forum.Element("lastpost").Element("user").Element("url").Value,
Photo = forum.Element("lastpost").Element("user").Element("photo").Value,
}
}
}).ToList();
}
}
}
它的基本功能是解析此地址返回的xml中的信息:
http://www.dreamincode.net/forums/xml.php?showforum=1
以下是我运行此代码的方式:
SharpDIC.Entities.Forum forum = new SharpDIC.Entities.Forum("1");
Console.WriteLine(forum.Name);
Console.WriteLine(forum.URL);
Console.WriteLine(forum.ID);
Console.WriteLine(forum.Subforums[0].LastPost.UserWhoPosted.Name);
Console.ReadLine();
我在整个加载子论坛块上遇到异常;有什么建议吗?
NullReferenceException was not handled. Object reference not set to an instance of an object.
答案 0 :(得分:1)
几乎可以肯定的是,你所期待的元素之一缺失了。
如果你在调试器中运行它,你可以 找到它抛出异常的时候,它会指示它在哪个实际操作,这会使它更容易。
或者,将各个组件解析为单独的方法:
this.Subforums = subforumsXML.Descendants("forum")
.Select(ParseForum)
.ToList();
...
static SubForum ParseForum(XElement forum)
{
return new Subforum
{
ID = forum.Element("id").Value,
...
LastPost = ParseLastPost(forum.Element("lastpost"))
};
}
static LastPost ParseLastPost(XElement lastPost)
{
...
}
我发现这可以使查询表达式更易于管理。
当您尝试获取值的缺失元素时,避免NRE的一种方法是使用转换而不是Value
属性,例如
ID = (string) forum.Element("id")
如果缺少null
元素,则会将ID设置为id
。显然,如果它实际上是 required 属性,抛出异常会更好,但对于可选属性,它确实非常有用。
答案 1 :(得分:0)
在使用你的linq之前,你应该检查以确保subforumsXML
!= null。
你可以把这个操作分成两行......
var subforumsXML = xml.Element("ipb").Element("forum").Element("subforums");
// goes to
if ( forumXML != null ) // breakpoint here
{
// ml.Element("ipb").Element("forum") == forumXML
var subforumsXML = forumXML.Element("subforums");
if ( subforumsXML != null )
{
// do stuff here
}
}
答案 2 :(得分:0)
您永远不会检查元素是否存在。例如,对于UserWhoPosted,每个项目必须具有<lastpost>
元素,必须具有<user>
元素,必须具有<id>
元素,<name>
,<url>
和<photo>
元素。如果缺少任何元素,那么Element(“whatever”)将返回null,因此.Value
将失败。
答案 3 :(得分:0)
在您的链接中,第一个用户没有照片,这可能是
答案 4 :(得分:0)
要找到问题,请尝试使用此扩展程序,然后调用GetElement而不是Element ...
public static System.Xml.Linq.XElement GetElement(this System.Xml.Linq.XContainer doc, string name)
{
var element = doc.Element(name);
if (element == null)
throw new ApplicationException("Missing element: " + name);
return element;
}