This is not a duplicate post, but a followup question to the one I have on UnityAnswers : http://answers.unity3d.com/questions/598425/how-to-read-data-with-saving-and-loading-data-xmls.html While the reference links in the answer and comments given by the person who answered are thoughtful, I have tried and have gotten nowhere. So in the meantime (as I'm very keen to get this implemented to continue working on my project), I'm trying to use a method from the comment by trothmaster in this post : http://forum.unity3d.com/threads/44441-XML-Reading-a-XML-file-in-Unity-How-to-do-it I wish to read an XML file, find a specific key, then read and store the sub-element values under that object. This is my idea on how it should work : Code (csharp): <MyClass> <MySubClass> <MyObject key = "KeyText"> <MySubElement1>someInfo</MySubElement1> <MySubElement2>someMoreInfo</MySubElement2> <MySubElement3>yetMoreInfo</MySubElement3> </MyObject> <MyObject key = "AnotherKeyText"> <MySubElement1>someInfo</MySubElement1> <MySubElement2>someMoreInfo</MySubElement2> <MySubElement3>yetMoreInfo</MySubElement3> </MyObject> </MySubClass> </MyClass> So this is my actual test XML : Code (csharp): <MonsterCollection> <Monsters> <Monster name="EarthDragon"> <Health>45</Health> <Attack>49</Attack> <Defense>49</Defense> </Monster> <Monster name="FireDragon"> <Health>39</Health> <Attack>52</Attack> <Defense>43</Defense> </Monster> </Monsters> </MonsterCollection> And the script I am working with : Code (csharp): #pragma strict import System.Xml; // for XmlDocument function Start() { var doc : XmlDocument = new XmlDocument(); doc.Load( Application.dataPath + "/monsters.xml" ); var root : XmlNode = doc.DocumentElement; Debug.Log( root.Name ); // Here is MyClass (MonsterCollection) var nodeList : XmlNodeList; // who knows what this does nodeList = root.SelectNodes( "Monsters" ); // this filters out MySubClass (sub-class Monsters) // if I have other sub-classes, I can filter them by whatever they're called (eg MySubClass2) nodeList = nodeList[0].ChildNodes; // this creates a list of all MyObjects within MySubClass Debug.Log( nodeList.Count ); // this shows I have 2 objects within MySubClass (called Monster) // loop through each of MyObjects for ( var i : int = 0; i < nodeList.Count; i ++ ) { Debug.Log( nodeList[i].Attributes["name"].Value ); // This Shows MyObject[i] key (name = "foo") // Now how do I get the value of each MySubElement under MyObject[i] ???? //Debug.Log( nodeList[i].Attributes.Element["Health"].Value ); // MySubElement1 //Debug.Log( nodeList[i].Attributes.Element["Attack"].Value ); // MySubElement2 //Debug.Log( nodeList[i].Attributes.Element["Defense"].Value ); // MySubElement3 } } As stated in the comment, how do I read and store the value in each sub-element within a MyObject that is found by a specified key?
Thanks for the suggestion, that gets me one step closer. However, all the values return null : Code (csharp): Debug.Log( nodeList[i].ChildNodes[0].Value ); // returns null Debug.Log( nodeList[i].ChildNodes[1].Value ); // returns null Debug.Log( nodeList[i].ChildNodes[2].Value ); // returns null Do you know the correct syntax to get the ChildNodes[x] XmlElement name and value?
Code (csharp): // reading for ( var i : int = 0; i < nodeList.Count; i++ ) { var node = nodeList[i]; Debug.Log(node.Attributes["name"].Value ); Debug.Log(node.SelectSingleNode("Health").InnerText); Debug.Log(node.SelectSingleNode("Attack").InnerText); Debug.Log(node.SelectSingleNode("Defense").InnerText); } // writing var earthDragonNode = monstersNode.SelectSingleNode("Monster[@name='FireDragon']"); earthDragonNode.SelectSingleNode("Health").InnerText = "77"; Debug.Log(doc.OuterXml); doc.Save(pathToFile); I will try to post a few snippets related to XML serialization later. EDIT: You can use ChildNodes too, but you have to use InnerText instead of Value.
Thank you for all your help, that has indeed solved the problem on this question. I just need to understand what the handles are to move around an xml file and extract the information in various layers. Not long ago I learned HashTables, and I thought this would be just as fun, turned out to be very confusing. Like I said on UA, I will still learn all about xml, I've put too much time in to give up now. Thanks again, you've been a great help.
Code (csharp): using System.Xml.Serialization; public class MonsterCollection { public Monster[] Monsters; } public class Monster { [XmlAttribute("name")] public string Name; public int Health; public int Attack; public int Defense; } Code (csharp): FileStream fs = new FileStream("data.xml", FileMode.Open); MonsterCollection monsters; XmlSerializer serial = new XmlSerializer(typeof(MonsterCollection)); monsters = serial.Deserialize(fs);
This DANGIT!!!! I can't for the life of me understand why anyone would use the horribly clunky XMLDoc stuff. Using the XMLSerializer makes it so incredibly easy to read and write .net objects.
Thanks, though I should point out I'm coding un uJS. This whole problem started when trying to follow the Unity Wiki tutorial on XmlSerializer : http://answers.unity3d.com/questions/598425/how-to-read-data-with-saving-and-loading-data-xmls.html At the end, the read example uses a type/class that doesn't exist, and there are no examples on how to extract the data once the xml has been deserialized. If you don't want to read the whole question, here are some highlights : Now I understand there is no class named MonsterCollection therefore the type doesn't exist, but I'm following a 'tutorial', I've never done this before and frankly don't know what I'm supposed to do. Is this thing supposed to recognize MonsterCollection as the root element of the xml? Am I missing a class? how can that wiki entry be of any use to a newcomer using xml when it's open-ended and doesn't work? It would have been great if the author of that wiki actually showed how to filter out and loop through the attributes, then gather the subchild nested elements. Basically people who know how to use xml wouldn't need that wiki, and people like me (with no clue) are left in the dark, totally useless.
Translation of the code posted by KelsoMRK to uJS is quite easy. One difference might be related to uJS convention used in Unity - variable names are camelcase, so they won't map directly to the elements in sample file. That's why I added a few additional attributes: Code (csharp): class MonsterCollection { @XmlArray("Monsters") var monsters : Monster[]; } class Monster { @XmlAttribute("name") var name : String; @XmlElement("Health") var health : int; @XmlElement("Attack") var attack : int; @XmlElement("Defense") var defense : int; } Code (csharp): var fs : FileStream = new FileStream(pathToFile, FileMode.Open); var s : XmlSerializer = new XmlSerializer(typeof(MonsterCollection)); var collection : MonsterCollection; collection = s.Deserialize(fs) as MonsterCollection; fs.Dispose(); and iterating through monsters: Code (csharp): for (monster in collection.monsters) { Debug.Log(monster.name); Debug.Log(monster.health); Debug.Log(monster.attack); Debug.Log(monster.defense); }
Thanks for that ArkaneX. The last comment was just a quick one before I walked out the door, and was more about how cranky I still am about the wiki tutorial being so incomplete (rather than the helpful comment that was left byKelsoMRK was in C#). Thanks to everyone who commented here. Now that you've fixed the error in my question with the deserializer, am going to start looking at how I can extract data from the collection like the above examples and your comment on my question : Anyway - now you have your monster collection filled with your dragon data from file. And they're already standard .NET classes, not XML data any more, so you can iterate using for or foreach, you can use LINQ, etc Thank you all for your time and patience dealing with someone who is self-taught and has no experience in xml.
This seems like a great way of working with XML, but unless I'm misunderstanding your example this is for creating xml attributes. How can you relate this to reading and using data from files?
Please take a look at the second code fragment from my last post. Data that is used to create instance of a MonsterCollection class (through deserialization) is read from file, with help of a FileStream.
Here is the solution to all your problems. https://forum.unity.com/threads/how-to-write-xml-in-unity.742241/unread