2010-03-13 79 views
7

我很难做这个看似简单的任务。我想加载XML文件与加载艺术资产一样容易:XNA:加载和读取XML文件的最佳方法?

 content = new ContentManager(Services); 
     content.RootDirectory = "Content"; 
     Texture2d background = content.Load<Texture2D>("images\\ice"); 

我不知道如何做到这一点。这tutorial似乎有帮助,但我怎么得到一个StorageDevice实例?

我有现在一些工作,但感觉很哈克:

public IDictionary<string, string> Get(string typeName) 
     { 
      IDictionary<String, String> result = new Dictionary<String, String>(); 
      xmlReader.Read(); // get past the XML declaration 

      string element = null; 
      string text = null; 

      while (xmlReader.Read()) 
      { 

       switch (xmlReader.NodeType) 
       { 
        case XmlNodeType.Element: 
         element = xmlReader.Name; 
         break; 
        case XmlNodeType.Text: 
         text = xmlReader.Value; 
         break; 
       } 

       if (text != null && element != null) 
       { 
        result[element] = text; 
        text = null; 
        element = null; 
       } 

      } 
      return result; 
     } 

我将此下面的XML文件:

<?xml version="1.0" encoding="utf-8" ?> 
<zombies> 
    <zombie> 
    <health>100</health> 
    <positionX>23</positionX> 
    <positionY>12</positionY> 
    <speed>2</speed> 
    </zombie> 
</zombies> 

而且它能够通过这个单元测试:

internal virtual IPersistentState CreateIPersistentState(string fullpath) 
    { 
     IPersistentState target = new ReadWriteXML(File.Open(fullpath, FileMode.Open)); 
     return target; 
    } 

    /// <summary> 
    ///A test for Get with one zombie. 
    ///</summary> 
    //[TestMethod()] 
    public void SimpleGetTest() 
    { 
     string fullPath = "C:\\pathTo\\Data\\SavedZombies.xml"; 
     IPersistentState target = CreateIPersistentState(fullPath); 
     string typeName = "zombie"; 

     IDictionary<string, string> expected = new Dictionary<string, string>(); 
     expected["health"] = "100"; 
     expected["positionX"] = "23"; 
     expected["positionY"] = "12"; 
     expected["speed"] = "2"; 

     IDictionary<string, string> actual = target.Get(typeName); 

     foreach (KeyValuePair<string, string> entry in expected) 
     { 
      Assert.AreEqual(entry.Value, expected[entry.Key]); 
     } 
    } 

目前方法的缺点:文件加载效果不佳,并且键与值匹配就像它比必要的更努力。另外,我怀疑这种方法会在XML中出现多个条目而崩溃。

我无法想象这是最佳实施。

UPDATE:继@Peter Lillevold的建议,我已经改变了这一点:

​​

加载仍然是相当糟糕的,并不知我是不是能够得到单行ToDictionary与这两个lambda一起工作。我不得不求助于那个foreach循环。我在那里做错了什么?

+0

你有一个错字。我的示例中的@只能与字符串文字一起使用,而不能与字符串变量或参数一起使用。 – 2010-03-14 02:58:24

+1

你知道XNA内容管道ALREADY支持XML文件,不是吗?因此,可以从字面上使用与加载艺术文件来加载XML文件相同的语法。 – 2011-07-05 05:16:27

回答

8

还有新的和有光泽的​​(其中运动Linq to XML)。此示例将加载一个XML文件,查找僵尸和转储值到字典:

var doc = XElement.Load("filename"); 
var zombieValues = doc.Element("zombie").Elements(); 
var zombieDictionary = 
    zombieValues.ToDictionary(
     element => element.Name.ToString(), 
     element => element.Value); 

如果你宁愿挑明确每个值(并使用铸造自动转换成适当的值类型),你可以这样做:

var zombie = doc.Element("zombie"); 
var health = (int)zombie.Element("health"); 
var positionX = (int)zombie.Element("positionX"); 
var positionY = (int)zombie.Element("positionY"); 
var speed = (int)zombie.Element("speed"); 

更新:固定一些错别字和清理了一下,你的Get方法应该是这样的:

public IDictionary<string, string> Get(string typeName) 
{ 
    var zombie = root.Element(typeName); 
    return zombie.Elements() 
      .ToDictionary(
        element => element.Name.ToString(), 
        element => element.Value); 
} 
+0

而且,“僵尸”前的@符号有什么意义? – 2010-03-14 02:23:58

+0

另外,我怎样才能比uri更优雅地加载文件? (就像内容管道一样?) – 2010-03-14 02:28:40

+0

对不起,这里@没有必要。当字符串应该是逐字的时候,它用在字符串前面。 你可以看看为你的文件类型制作一个自定义的流水线处理器。看看这个:http://msdn.microsoft.com/en-us/library/bb447754.aspx – 2010-03-14 02:54:06

2
System.Xml.XmlDocument doc = new System.Xml.XmlDocument(); 
doc.LoadXml(xmlString); 

string health = doc["zombies"]["zombie"]["health"].InnerText; 
// etc.. 

// or looping 

foreach(XmlNode node in doc["zombies"].ChildNodes) 
{ 
    string health = node["health"].InnerText; 
    // etc... 
} 

或者这在XNA中不起作用?

+0

我会试试。但是,首先从文件中获取xmlString的更好方法是什么? – 2010-03-13 21:06:01

+0

更新了代码,因为我犯了一个错误。 (doc.Load => doc.LoadXml) – TJMonk15 2010-03-14 01:25:24

+0

似乎XmlDocument不包含在.NET的XNA发行版中,或者至少在我尝试使用它时抱怨。 – Arkiliknam 2012-12-16 15:32:34