1

プログラムの設定を含むxml構成ファイルを持つac#コンソールアプリケーションに取り組んでいます。

を使用して特定の設定に使用できる値を示すために、xml ファイルにコメントを追加したかったのです<!--My Comment-->。なんらかの理由で、これを挿入すると、C# がこれがファイルの終わりであり、ファイルの他の部分が読み取られていないと考えているかのように、エラーはスローされず、プログラムは応答を停止せず、残りを実行し続けますコードの。

以下は設定ファイルです。

<?xml version="1.0" encoding="utf-8" ?>
<options>
  <database>
    <item key="server" value="localhost" />
    <item key="database" value="emailserver" />
    <item key="username" value="myusername" />
    <item key="password" value="mypassword" />
    <item key="port" value="3306" />
  </database>
  <EmailServer>
    <item key="logFile" value="email_server.txt" />
    <!--You can use fileCopy or database-->
    <item key="logManageMode" value="fileCopy" />
    <item key="ip_address" value="127.0.0.1" />
    <item key="smtpPort" value="26" />
    <item key="requireAuthentication" value="false" />
  </EmailServer>
</options>

そのコメントを入れないと、ファイル全体が読み込まれます。以下は、XML ファイルを読み取るコードです。

public Dictionary<string, string> readConfig(string sectionName, bool soapService=false, Dictionary<string, string> config=null)
        {
            Dictionary<string, string> newConfig = null;
            if (config == null)
            {
                newConfig = new Dictionary<string, string>();
            }
            //Dictionary<string, string> config = new Dictionary<string, string>();
            try
            {
                XmlDocument configXml = new XmlDocument();
                string configPath = "";
                if (soapService)
                {
                    string applicationPath = HttpContext.Current.Server.MapPath(null);
                    configPath = Path.Combine(applicationPath, "config.xml");
                    configXml.Load(configPath);
                }
                else
                {
                    configXml.Load("config.xml");
                }

                XmlNodeList options = configXml.SelectNodes(string.Format("/options/{0}", sectionName));
                XmlNodeList parameters = configXml.GetElementsByTagName("item");
                foreach (XmlNode option in options)
                {
                    foreach (XmlNode setting in option)
                    {
                        string key = setting.Attributes["key"].Value;
                        string value = setting.Attributes["value"].Value;

                        if (config == null)
                        {
                            newConfig.Add(key, value);
                        }
                        else
                        {
                            config.Add(key, value);
                        }
                    }
                }
            }
            catch (KeyNotFoundException ex)
            {
                Console.WriteLine("Config KeyNotFoundException: {0}", ex.Message);
            }
            catch (XmlException ex)
            {
                Console.WriteLine("Config XmlException: {0}", ex.Message);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Config Exception: {0}", ex.Message);
                Console.WriteLine("StackTrace: {0}", ex.StackTrace);
            }
            if (config == null)
            {
                return newConfig;
            }
            return config;
        }

ご協力いただきありがとうございます。

4

2 に答える 2

4

あなたのコメントはノードです。したがって、ノードをループすると:

 foreach (XmlNode option in options) 
                 { 
                     foreach (XmlNode setting in option) 
                     { 
                         string key = setting.Attributes["key"].Value; 
                         string value = setting.Attributes["value"].Value;

そのノードには「キー」または「値」属性が含まれていないため、commebnt で try/catch ブロックをトリップしています。

プロパティを使用してNodeType、ノードがコメントかどうかを判断できます。例えば:

 foreach (XmlNode option in options) 
                 { 
                     foreach (XmlNode setting in option) 
                     { 
                         if (setting.NodeType == XmlNodeType.Comment)
                         {
                             continue;
                         }
                         string key = setting.Attributes["key"].Value; 
                         string value = setting.Attributes["value"].Value;

別のオプションは、ノードが要素でない場合に続行することです。

if (setting.NodeType != XmlNodeType.Element)

Tomalak によると: 実際、これは OP の元のコードと同じくらい脆弱です。コメントとは異なるノード タイプを XML に挿入すると、再び爆発します。ループ内で特定の XmlNodeList を選択するだけです。 XmlNodeList settings = option.SelectNodes("item[@key and @value]");

于 2012-08-15T17:27:04.220 に答える
1

これは、未知の XML ノード タイプで詰まることがなく、少し短いバージョンのコードです。

重要な点は、子ノードのリストを単純にループして、ノードが特定のものであると期待することはできないということです。

特定のノードで作業する場合は、常に特定のもの(この場合は と属性itemを含む名前の要素ノード) を選択してください。@key@value

XmlNodeList settings = option.SelectNodes("./item[@key and @value]");

完全なコードは次のとおりです。

public Dictionary<string, string> readConfig(string sectionName, bool soapService=false, Dictionary<string, string> config=null)
{
    Dictionary<string, string> myConfig = config ?? new Dictionary<string, string>();
    try
    {
        XmlDocument configXml = new XmlDocument();
        string configPath = "config.xml";
        if (soapService)
        {
            string applicationPath = HttpContext.Current.Server.MapPath(null);
            configPath = Path.Combine(applicationPath, "config.xml");
        }
        configXml.Load(configPath);

        XmlNodeList options = configXml.SelectNodes(string.Format("/options/{0}", sectionName));
        foreach (XmlNode option in options)
        {
            XmlNodeList settings = option.SelectNodes("./item[@key and @value]");
            foreach (XmlNode setting in settings)
            {
                myConfig.Add(setting.Attributes["key"].Value, setting.Attributes["value"].Value);
            }
        }
    }
    catch (KeyNotFoundException ex)
    {
        Console.WriteLine("Config KeyNotFoundException: {0}", ex.Message);
    }
    catch (XmlException ex)
    {
        Console.WriteLine("Config XmlException: {0}", ex.Message);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Config Exception: {0}", ex.Message);
        Console.WriteLine("StackTrace: {0}", ex.StackTrace);
    }
    return myConfig;
}
于 2012-08-15T17:47:54.967 に答える