XmlDocument C#遇到问题

时间:2009-11-17 00:51:14

标签: c# xml xmldocument nullreferenceexception

我无法让我的程序正确读取这个XML文件,它还需要写入它但尚未写入。请注意,这只是代码的一小部分

XmlDocument InstalledList = new XmlDocument();
InstalledList.Load(AppsInstalledFileNamePath);

//Sets the PackageNode to the correct part of the XmlDocument
XmlNodeList PackagesNode = InstalledList.GetElementsByTagName("installed");

foreach (XmlNode InstalledListNodes in PackagesNode)
{
    //If the title is the same as what the user typed, continue on
    if (InstalledListNodes.Attributes["title"].InnerText.Equals(packagename) == true)
    {
        BatchProcessFileName = InstalledListNodes.Attributes["uninstallername"].InnerText;
        Console.WriteLine("Filename OK");

我也把try语句拿出来,所以我不必添加catch

下面是它试图读取(后来写入)的XML文件

<?xml version="1.0" encoding="utf-8" ?>
<packages>
  <installed>
  <sampleapp title="sampleapp" id="00001" uninstallername="sampleapp.bat" installdate="11/15/09"></sampleapp>
  <sampleapp2 title="sampleapp2" id="00002" uninstallername="sampleapp2.bat" installdate="11/16/09"></sampleapp2>
  </installed>
  <uninstalled>

 </uninstalled>
</packages>

代码运行,但在

处有一个NullReference异常
InstalledListNodes.Attributes["title"].InnerText.Equals(packagename) == true

3 个答案:

答案 0 :(得分:1)

嗯,我可以在以下行看到三个不同的失败点:

InstalledListNodes.Attributes["title"].InnerText.Equals(packagename) == true
   ^--Null?                 ^-- Null?    ^--Null?

我会将这个长链分解为更多离散元素,并在每个元素上检查null以缩小它:

   if (InstalledListNodes != null)
   {
       var attribute = InstalledListNodes.Attributes["title"]; 
       if (attribute != null)
       {
           if (attribute.InnerText.Equals(packagename) == true)
           {
              // ...
           }
       }
   }

也就是说,在检索属性值时,我会使用 .Value 属性而不是 .InnerText 属性。从元素打开和关闭标记中检索文本内容时,应使用InnerText。

答案 1 :(得分:1)

似乎是一个小错字;

请注意,您写了Attributes["unintallername"],它应该是Attributes["uninstallername"]

答案 2 :(得分:1)

仅供参考,与普遍认为相反: InnerText对于属性或元素null。这意味着,您根本不必检查InnerText是否为空。空元素和属性的InnerText空字符串:

XmlDocument docx = new XmlDocument();
docx.LoadXml("<root test='' />");
Debug.WriteLine("Empty: " + docx.FirstChild.InnerText);
Debug.WriteLine("Empty: " + docx.FirstChild.Attributes["test"].InnerText);

但是,如果属性本身不存在,则属性本身可以返回null。正如jrista已经指出的那样,除非你真的必须使用InnerText,否则它是无用的。坚持Value而不是。{/ p>


解决您的问题

许多人已对此发表评论。你有:

XmlNodeList PackagesNode = InstalledList.GetElementsByTagName("installed");
foreach (XmlNode InstalledListNodes in PackagesNode)
{
    if (InstalledListNodes.Attributes["title"].InnerText.Equals(packagename) == true)
    ....

使用您显示的XML,这将无法工作,因为<installed>没有属性。尝试:

XmlNodeList PackagesNode = InstalledList.GetElementsByTagName("installed");
foreach (XmlNode InstalledListNodes in PackagesNode)
{
    XmlNode someNode = InstalledListNodes.FirstChild;
    if (someNode.Attributes["title"].InnerText.Equals(packagename) == true)
    ....

它不会(还)提供你想要的效果,但是someNode现在指向一个实际拥有title属性的节点,向你展示如何摆脱这个错误。

更简单的解决方案:SelectNodes

删除错误后,我想以另一种方式向您展示:XPath。使用XPath,这种类型的任务实际上要容易得多。以下是我对你的问题的看法(未经测试):

// assuming <packages> is root:
XmlNodeList applicationNodes = InstalledList.SelectNodes("/packages/installed/*");

foreach (XmlNode applicationNode in applicationNodes)
{
     if (applicationNode.Attributes["title"].Value.Equals(packagename) == true)
     { 
     .... etc

重要提示:其他人所说的关于检查节点步骤返回值的内容仍然非常重要。如果您的输入数据不存在,那么您的代码将会很难实现。只需始终检查每一步,或使用更多XPath,让您的生活更轻松。

更新: 仅供参考 更新:添加了解决方案
更新:添加了替代解决方案(无法抗拒)