Возникли проблемы с XmlDocument C # - PullRequest
1 голос
/ 17 ноября 2009

У меня проблемы с тем, чтобы моя программа правильно прочитала этот 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, чтобы мне не пришлось добавлять улов

Ниже приведен 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 ]

1 голос
/ 17 ноября 2009

Кажется маленькая опечатка;

Обратите внимание, что вы написали Attributes["unintallername"], и оно должно быть Attributes["uninstallername"]

1 голос
/ 17 ноября 2009

К вашему сведению и вопреки распространенному мнению: 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, чтобы сделать вашу жизнь проще.

Обновление: К вашему сведению
Обновление: добавлено решение
Обновление: добавлено альтернативное решение (не устоял)

1 голос
/ 17 ноября 2009

Хорошо, я вижу три разных точки отказа в следующей строке:

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

Я бы разбил эту длинную цепочку на более дискретные элементы и проверил бы на нулевое значение на каждом, чтобы сузить ее:

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

Тем не менее, я бы использовал свойство .Value вместо свойства .InnerText при получении значений атрибута. InnerText следует использовать при извлечении текстового содержимого из тегов открытия и закрытия элемента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...