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 ステートメントも削除しました。

以下は、読み取ろうとしている(そして後で書き込もうとしている)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 Exception があります。

InstalledListNodes.Attributes["title"].InnerText.Equals(packagename) == true
4

3 に答える 3

1

さて、次の行で 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)
           {
              // ...
           }
       }
   }

つまり、属性値を取得するときは、 .InnerTextプロパティではなく.Valueプロパティを使用します。InnerText は、要素の開始タグと終了タグ内からテキスト コンテンツを取得するときに使用する必要があります。

于 2009-11-17T00:58:17.653 に答える
1

小さなタイプミスのようです。

あなたが書いたことに注意Attributes["unintallername"]してください。Attributes["uninstallername"]

于 2009-11-17T01:03:30.653 に答える
1

参考までに、一般に信じられていることとは反対に、属性や要素にInnerTextは決してnull使用されません。つまり、InnerTextnull であることを確認する必要はまったくありません。空の要素と属性には、次の空の文字列があります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 に答える