1

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

3 回答 3

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。

于 2009-11-17T00:58:17.653 回答
1

似乎是一个小错字;

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

于 2009-11-17T01:03:30.653 回答
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,这将永远无法工作,因为<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 来让您的生活更轻松。

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

于 2009-11-17T01:03:57.910 回答