Я испытываю затруднения при выполнении этой на вид простой задачи. Я хочу загрузить XML-файлы той же простотой загрузки художественных активов:
content = new ContentManager(Services);
content.RootDirectory = "Content";
Texture2d background = content.Load("images\\ice");
Я не уверен, как сделать это. Это учебное руководство кажется полезным, но как я получаю a StorageDevice
экземпляр?
У меня действительно есть что-то работающее теперь, но это чувствует симпатичный hacky:
public IDictionary Get(string typeName)
{
IDictionary result = new Dictionary();
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-файлу:
100
23
12
2
И это может передать этот модульный тест:
internal virtual IPersistentState CreateIPersistentState(string fullpath)
{
IPersistentState target = new ReadWriteXML(File.Open(fullpath, FileMode.Open));
return target;
}
///
///A test for Get with one zombie.
///
//[TestMethod()]
public void SimpleGetTest()
{
string fullPath = "C:\\pathTo\\Data\\SavedZombies.xml";
IPersistentState target = CreateIPersistentState(fullPath);
string typeName = "zombie";
IDictionary expected = new Dictionary();
expected["health"] = "100";
expected["positionX"] = "23";
expected["positionY"] = "12";
expected["speed"] = "2";
IDictionary actual = target.Get(typeName);
foreach (KeyValuePair entry in expected)
{
Assert.AreEqual(entry.Value, expected[entry.Key]);
}
}
Оборотные стороны к текущему подходу: загрузка файла сделана плохо, и соответствие ключам к значениям кажется, что это - путь больше усилия, чем необходимый. Кроме того, я подозреваю, что этот подход развалился бы больше чем с одной записью в XML.
Я не могу предположить, что это - оптимальная реализация.
ОБНОВЛЕНИЕ: Следуя совету @Peter Lillevold, я изменил это немного:
public IDictionary Get(string typeName)
{
IDictionary result = new Dictionary();
IEnumerable zombieValues = root.Element(@typeName).Elements();
//result["health"] = zombie.Element("health").ToString();
IDictionary nameToElement = zombieValues.ToDictionary(element => element.Name.ToString());
foreach (KeyValuePair entry in nameToElement)
{
result[entry.Key] = entry.Value.FirstNode.ToString();
}
return result;
}
public ReadWriteXML(string uri)
{
root = XElement.Load(uri);
}
internal virtual IPersistentState CreateIPersistentState(string fullpath)
{
return new ReadWriteXML(fullpath);
}
///
///A test for Get with one zombie.
///
[TestMethod()]
public void SimpleGetTest()
{
IPersistentState target = CreateIPersistentState("../../../path/Data/SavedZombies.xml");
string typeName = "zombie";
IDictionary expected = new Dictionary();
expected["health"] = "100";
expected["positionX"] = "23";
expected["positionY"] = "12";
expected["speed"] = "2";
IDictionary actual = target.Get(typeName);
foreach (KeyValuePair entry in expected)
{
Assert.AreEqual(entry.Value, actual[entry.Key]);
}
}
Загрузка является все еще довольно дрянной, и так или иначе я не смог получить короткое ToDictionary
работать с теми двумя лямбдами. Я должен был обратиться к тому циклу foreach. Что я делаю неправильно там?
Существует также новый и блестящий XElement (который является спортивным 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);
}
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?