Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C中读取带有属性的XML时出现问题#_C#_Xml_Nodes - Fatal编程技术网

C# 在C中读取带有属性的XML时出现问题#

C# 在C中读取带有属性的XML时出现问题#,c#,xml,nodes,C#,Xml,Nodes,我正在制作一个应用程序,用于保存和加载XML文件中的数据 以下是我的xml: <?xml version="1.0" encoding="utf-8" ?> <storage> <Save Name ="Lifeline"> <Seconds>12</Seconds> <Minutes>24</Minutes> <Hours>9</Hours> <Days>25

我正在制作一个应用程序,用于保存和加载XML文件中的数据

以下是我的xml:

<?xml version="1.0" encoding="utf-8" ?> 
<storage>   
<Save Name ="Lifeline">
 <Seconds>12</Seconds>
 <Minutes>24</Minutes>
 <Hours>9</Hours>
 <Days>25</Days>
 <Months>8</Months>
 <Years>2010</Years>
 <Health>90</Health>
 <Mood>100</Mood>  
</Save> 

<Save Name ="Hellcode">   
 <Seconds>24</Seconds>
 <Minutes>48</Minutes>
 <Hours>18</Hours>
 <Days>15</Days>
 <Months>4</Months>
 <Years>1995</Years>
 <Health>50</Health>
 <Mood>50</Mood>  
</Save> 
</storage>
当我尝试运行应用程序时,编译器给出了NullReferenceException未处理“对象引用未设置为对象的实例”

所以我的问题是什么错了,我该怎么办

编辑: 我甚至试过这个

foreach (XmlNode xn in saveItems)
{
 sec = Int32.Parse(xn["Seconds"].InnerText);
 min = Int32.Parse(xn["Minutes"].InnerText);
 hour = Int32.Parse(xn["Hours"].InnerText);
 day = Int32.Parse(xn["Days"].InnerText);
 month = Int32.Parse(xn["Months"].InnerText);
 year = Int32.Parse(xn["Years"].InnerText);
 health = Int32.Parse(xn["Health"].InnerText);
 mood = Int32.Parse(xn["Mood"].InnerText);
}
但什么也装不下

===================================================================

只是为了让这个问题更容易理解。 下面的代码可以工作并加载应用程序所需的所有数据,但它只从“生命线”节点加载。在编译时,没有例外,所有的工作都很好

System.IO.StreamReader sr=新的System.IO.StreamReader(@“Saves.xml”)

问题是,我希望能够通过“Name”属性选择节点,但我不知道如何使用列表框进行选择。
这些“生命线”和“Hellcode”类似于帐户名,用户应该选择加载哪个帐户数据。

您的XPath查询已关闭-您当前使用的是名称作为文本,而不是其值,还需要在其周围加上单引号-因此请替换此项

XmlNodeList saveItems = save.SelectNodes("Storage/Save[@Name = name]");
与:

编辑:在Xpath查询中还需要小写
存储
-修复

此示例代码适用于我-这将帮助您找到其他问题所在:

System.IO.StreamReader sr = new System.IO.StreamReader(@"test.xml");
System.Xml.XmlTextReader xr = new System.Xml.XmlTextReader(sr);
System.Xml.XmlDocument save = new System.Xml.XmlDocument();
save.Load(xr);
string name = "Hellcode";
XmlNodeList saveItems = save.SelectNodes(string.Format("storage/Save[@Name = '{0}']", name));

XmlNode seconds = saveItems.Item(0).SelectSingleNode("Seconds");
int sec = Int32.Parse(seconds.InnerText);
另外,我建议您将
SelectNodes()
替换为
SelectSingleNode()

编辑:

正如所建议的,XML解析的另一种替代方法是Linq到XML——这几乎是现在的标准,如果不需要的话,不要使用任何其他方法。这使得此示例更短:

XDocument doc = XDocument.Load("test.xml");
var saveItem = doc.Descendants("Save")
                  .Where(x => (string)x.Attribute("Name") == name)
                  .Single();
int sec = Convert.ToInt32(saveItem.Element("Seconds").Value);

您的XPath查询已关闭-您当前使用的是名称作为文本,而不是其值,并且需要在其周围加上单引号-因此请替换此项

XmlNodeList saveItems = save.SelectNodes("Storage/Save[@Name = name]");
与:

编辑:在Xpath查询中还需要小写
存储
-修复

此示例代码适用于我-这将帮助您找到其他问题所在:

System.IO.StreamReader sr = new System.IO.StreamReader(@"test.xml");
System.Xml.XmlTextReader xr = new System.Xml.XmlTextReader(sr);
System.Xml.XmlDocument save = new System.Xml.XmlDocument();
save.Load(xr);
string name = "Hellcode";
XmlNodeList saveItems = save.SelectNodes(string.Format("storage/Save[@Name = '{0}']", name));

XmlNode seconds = saveItems.Item(0).SelectSingleNode("Seconds");
int sec = Int32.Parse(seconds.InnerText);
另外,我建议您将
SelectNodes()
替换为
SelectSingleNode()

编辑:

正如所建议的,XML解析的另一种替代方法是Linq到XML——这几乎是现在的标准,如果不需要的话,不要使用任何其他方法。这使得此示例更短:

XDocument doc = XDocument.Load("test.xml");
var saveItem = doc.Descendants("Save")
                  .Where(x => (string)x.Attribute("Name") == name)
                  .Single();
int sec = Convert.ToInt32(saveItem.Element("Seconds").Value);
  • 确保你给出了正确的答案 xml文件名
  • 确保您的xml文件不是空的
  • 然后尝试这个
    XmlNode seconds=saveItems.Item(0)。选择singlenode(“seconds”).Value
  • 检查
  • 检查
  • 确保你给出了正确的答案 xml文件名
  • 确保您的xml文件不是空的
  • 然后尝试这个
    XmlNode seconds=saveItems.Item(0)。选择singlenode(“seconds”).Value
  • 检查
  • 检查

  • 要回答您的其他重复问题,请执行以下操作:

    我试图从listbox项内容中提取字符串,然后使用这样一行

    XmlNodeList saveItems=save.SelectNodes(string.Format(“存储/保存[@Name='{0}'],Name))

    变量“name”是listboxe项中的字符串。在编译时,这段代码给出了异常。有人知道如何按属性选择并从XML加载nedeed数据吗

    我怀疑您没有从
    列表框中获取正确的值。这完全取决于您如何填充它。如果您只是使用设计器用
    字符串
    名称填充
    列表框
    ,则应使用该属性获取所选名称。另一方面,如果填充了列表框设置,请将属性设置为适当的属性名称,并使用获取值

    虽然你从未提及例外情况,但这只是一个有根据的猜测


    您最初的问题是使用了错误的XPath。因为它是错误的,所以对第一个结果的所有后续访问都返回了
    null
    ,产生了
    NullReferenceException
    。BrokenGlass的回答包括使用正确的XPath

    如果您向我们展示的XML确实是文件内容中的内容,并且您得到了适当的
    名称
    值,那么这里的一切都应该正常

    总的来说,代码可以简化得多。我在这里使用一些LINQ只是为了更容易地处理无效名称。您应该会发现这是一个有效的代码

    var xmlStr = @"<?xml version=""1.0"" encoding=""utf-8"" ?> 
    <storage>   
      <Save Name =""Lifeline"">
        <!-- etc... (trimmed off for brevity) -->
      </Save> 
      <Save Name =""Hellcode"">
        <!-- etc... -->
      </Save> 
    </storage>
    ";
    var doc = new XmlDocument();
    doc.LoadXml(xmlStr);
    var name = "Hellcode";
    var settings =
        doc.SelectNodes(String.Format("/storage/Save[@Name='{0}']", name))
           .Cast<XmlElement>()
           .Select(e => new
           {
               Seconds = Convert.ToInt32(e["Seconds"].InnerText),
               Minutes = Convert.ToInt32(e["Minutes"].InnerText),
               Hours   = Convert.ToInt32(e["Hours"].InnerText),
               Days    = Convert.ToInt32(e["Days"].InnerText),
               Months  = Convert.ToInt32(e["Months"].InnerText),
               Years   = Convert.ToInt32(e["Years"].InnerText),
               Health  = Convert.ToInt32(e["Health"].InnerText),
               Mood    = Convert.ToInt32(e["Mood"].InnerText),
           })
           .SingleOrDefault();
    Trace.WriteLine("settings: " + settings);
    

    要回答您的其他重复问题,请执行以下操作:

    我试图从listbox项内容中提取字符串,然后使用这样一行

    XmlNodeList saveItems=save.SelectNodes(string.Format(“存储/保存[@Name='{0}'],Name))

    变量“name”是listboxe项中的字符串。在编译时,这段代码给出了异常。有人知道如何按属性选择并从XML加载nedeed数据吗

    我怀疑您没有从
    列表框中获取正确的值。这完全取决于您如何填充它。如果您只是使用设计器用
    字符串
    名称填充
    列表框
    ,则应使用该属性获取所选名称。另一方面,如果填充了列表框设置,请将属性设置为适当的属性名称,并使用获取值

    虽然你从未提及例外情况,但这只是一个有根据的猜测


    您最初的问题是使用了错误的XPath。因为它是错误的,所以对第一个结果的所有后续访问都返回了
    null
    ,产生了
    NullReferenceException
    。BrokenGlass的回答包括使用正确的XPath

    如果您向我们展示的XML确实是文件内容中的内容,并且您得到了适当的
    名称
    值,那么这里的一切都应该正常

    总的来说,代码
    XDocument doc = XDocument.Load("test.xml");
    var saveItem = doc.Descendants("Save")
                      .Where(x => (string)x.Attribute("Name") == name)
                      .Single();
    int sec = Convert.ToInt32(saveItem.Element("Seconds").Value);
    
    var xmlStr = @"<?xml version=""1.0"" encoding=""utf-8"" ?> 
    <storage>   
      <Save Name =""Lifeline"">
        <!-- etc... (trimmed off for brevity) -->
      </Save> 
      <Save Name =""Hellcode"">
        <!-- etc... -->
      </Save> 
    </storage>
    ";
    var doc = new XmlDocument();
    doc.LoadXml(xmlStr);
    var name = "Hellcode";
    var settings =
        doc.SelectNodes(String.Format("/storage/Save[@Name='{0}']", name))
           .Cast<XmlElement>()
           .Select(e => new
           {
               Seconds = Convert.ToInt32(e["Seconds"].InnerText),
               Minutes = Convert.ToInt32(e["Minutes"].InnerText),
               Hours   = Convert.ToInt32(e["Hours"].InnerText),
               Days    = Convert.ToInt32(e["Days"].InnerText),
               Months  = Convert.ToInt32(e["Months"].InnerText),
               Years   = Convert.ToInt32(e["Years"].InnerText),
               Health  = Convert.ToInt32(e["Health"].InnerText),
               Mood    = Convert.ToInt32(e["Mood"].InnerText),
           })
           .SingleOrDefault();
    Trace.WriteLine("settings: " + settings);
    
    var doc = XDocument.Parse(xmlStr);
    var name = "Hellcode";
    var settings =
        doc.Element("storage")
           .Elements("Save")
           .Where(e => e.Attribute("Name").Value == name)
           // or if using XPath, the above could be replaced with:
    //  doc.XPathSelectElements(String.Format("/storage/Save[@Name='{0}']", name))
           .Select(e => new
           {
               Seconds = (int)e.Element("Seconds"),
               Minutes = (int)e.Element("Minutes"),
               Hours   = (int)e.Element("Hours"),
               Days    = (int)e.Element("Days"),
               Months  = (int)e.Element("Months"),
               Years   = (int)e.Element("Years"),
               Health  = (int)e.Element("Health"),
               Mood    = (int)e.Element("Mood"),
           })
           .SingleOrDefault();
    Trace.WriteLine("settings: " + settings);