【问题标题】:Having trouble with XmlDocument C#XmlDocument C# 遇到问题
【发布时间】:2009-11-17 00:51:13
【问题描述】:

我无法让我的程序正确读取此 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

【问题讨论】:

  • 次要:考虑将单数对象持有变量重命名为其单数英文名称,反之亦然:foreach (XmlNode InstalledListNode in PackagesNodes)
  • 我编辑了你的 q。稍微去掉了与XML处理无关的部分,希望大家不要介意。

标签: c# xml xmldocument nullreferenceexception


【解决方案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


解决您的问题

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

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

使用您展示的 XML,这将永远无法工作,因为 &lt;installed&gt; 没有属性。试试:

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

它不会(还)产生你想要的效果,但someNode 现在指向一个实际包含标题属性的节点,向你展示如何摆脱这个错误。

更简单的解决方案: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 让您的生活更轻松。

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

【讨论】:

  • 不客气! PS:您也可以使用 XPath 一次性选择您的包名,无需手动循环:SelectNodes(String.Format("packages/installed/*[title='{0}']", packagename))。省去很多麻烦!
  • 感谢您的反对,但请详细说明原因?我很乐意更新我的答案以纠正任何错误。
  • 我不小心又打了一次,对不起,它不会让我再打一次
【解决方案2】:

似乎是一个小错字;

注意你写的是Attributes["unintallername"],它应该是Attributes["uninstallername"]

【讨论】:

    【解决方案3】:

    嗯,我可以在下面一行中看到三个不同的故障点:

    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 完全同意空测试,但是...ValueInnerText 都不会为属性为空。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-01
    相关资源
    最近更新 更多