Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by AlucardJay · Dec 17, 2013 at 04:26 AM · xmlxmlserializer

How to read data with 'Saving and Loading Data : XmlSerializer'

I'm following the guide on the Unity Wiki : http://wiki.unity3d.com/index.php?title=Saving_and_Loading_Data:_XmlSerializer

I've created my monsters.xml, Monster.js and MonsterContainer.js and there are no errors.

Now in my test script :

 var dragonName : String = "EarthDragon";
 var baseHealth : int = 0;
 var baseAttack : int = 0;
 var baseDefense : int = 0;
 
 function Start() 
 {
     var monsterCollection : MonsterCollection = MonsterContainer.Load( Path.Combine( Application.dataPath, "monsters.xml" ) );
 }

this gives the error :

 Assets/_Scripts/XmlTest.js(48,33): BCE0018: The name 'MonsterCollection' does not denote a valid type ('not found'). 

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?

My goal is to read an Attribute of the root element by name, then populate my variables based on the values in nested elements under that Attribute. How can I achieve this?

The examples found here are using a completely different method to the wiki. The question here suggests using an available package, but I'm coding in uJS. Can anyone help me with this problem, understand why the guide is failing, and how I can populate my variables based on a name to reference an attribute (child element)? Thanks.


Further information :

monster.xml

 <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>

Monster.js

 import System.Xml;
 import System.Xml.Serialization;
 
 public class Monster
 {
     @XmlAttribute("name")
     public var name : String;
 
     public var health : int;
     public var attack : int;
     public var defense : int;
 }

MonsterContainer.js

 import System.Collections.Generic;
 import System.Xml;
 import System.IO;
 
 @XmlRoot("MonsterCollection")
 public class MonsterContainer
 {
     @XmlArray("Monsters")
     @XmlArrayItem("Monster")
     
     public var Monsters : List.< Monster > = new List.< Monster >();
 
     public function Save( path : String )
     {
         var serializer : XmlSerializer = new XmlSerializer( MonsterContainer );
         var stream : Stream = new FileStream( path, FileMode.Create );
         serializer.Serialize( stream, this );
         stream.Close();
     }
 
     public static function Load( path : String ) : MonsterContainer 
     {
         var serializer : XmlSerializer = new XmlSerializer( MonsterContainer );
         var stream : Stream = new FileStream( path, FileMode.Open );
         var result : MonsterContainer = serializer.Deserialize( stream ) as MonsterContainer;
         stream.Close();
         
         return result;
     }
     
     //Loads the xml directly from the given string. Useful in combination with www.text.
     public static function LoadFromText( text : String ) : MonsterContainer
     {
         var serializer : XmlSerializer = new XmlSerializer(MonsterContainer);
         return serializer.Deserialize(new StringReader(text)) as MonsterContainer;
     }
 }


Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image AlucardJay · Dec 17, 2013 at 06:02 AM 0
Share

Is there anyone on this website who is familiar with reading and writing to xml files?

I understand the process, just need the syntax.

  • Load the xml file to a temporary variable

  • read through the attributes of that temporary file (locate the key)

  • when the key is found, read all the nested elements under that key, storing each in my global variables

I'm more than capable of using StreamReader to read a whole file, and extract the information from there, but I thought this would be an easier way to look up a key and grab just a portion of the elements under that key. The guide I'm following has no mention of the type $$anonymous$$onsterCollection. How am I supposed to be reading the xml, finding the key, and extracting the sub-elements under that key?

avatar image AlucardJay · Dec 17, 2013 at 07:17 AM 0
Share

For example, I can get this to work

 var doc : XmlDocument = new XmlDocument();
 
 var path : String = Path.Combine( Application.dataPath, "monsters2.xml" );
 
 doc.Load( path );
 
 var nodeList : XmlNodeList;
 var root : XmlNode = doc.DocumentElement;
 
 nodeList = root.SelectNodes("$$anonymous$$onsters");  //this selects all nodes $$anonymous$$onsters
 
 nodeList = nodeList[0].ChildNodes;  //this rebuilds the list using all the childnodes from the nodes $$anonymous$$onsters
 
 
 for ( var i : int = 0; i < nodeList.Count; i++ ) 
 {
     Debug.Log( nodeList[i].Attributes["name"].Value );  
     Debug.Log( nodeList[i].Attributes["health"].Value ); 
     Debug.Log( nodeList[i].Attributes["attack"].Value ); 
     Debug.Log( nodeList[i].Attributes["defense"].Value ); 
 }

using the xml file

 <$$anonymous$$onsterCollection>
     <$$anonymous$$onsters>
         <$$anonymous$$onster name="EarthDragon"
             health="45"
             attack="49"
             defense="49">
         </$$anonymous$$onster>
         <$$anonymous$$onster name="FireDragon"
             health="39"
             attack="52"
             defense="43">
         </$$anonymous$$onster>
     </$$anonymous$$onsters>
 </$$anonymous$$onsterCollection>

so what's the point of using xml over a text file if I have to read the whole thing anyway? Well I suppose sorting by attribute and only checking a specific attribute is better than reading every line.

And how can that wiki entry be of any use to a newcomer using xml when it's open-ended and doesn't work?

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by ArkaneX · Dec 17, 2013 at 09:55 AM

I didn't test the code, but the line which gives you error is wrong and should be corrected in the wiki. Variable monsterCollection should be of type MonsterContainer instead of MonsterCollection.

In the wiki sample, author remapped a class MonsterContainer to a root XML element named MonsterCollection. After deserialization of this XML, you should have an instance of MonsterContainer class, not MonsterCollection class (because there is no such class). For me, such remapping might be a source of confusion, and I try to avoid this in most cases, especially if I can control the structure of XML.

If this mixing is no problem for you, just leave it as it is. But I would just change MonsterContainer class name to MonsterCollection.

Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image AlucardJay · Dec 17, 2013 at 10:27 AM 0
Share

Thanks ArkaneX, that does indeed remove the error. Unfortunately that's where the wiki ends, so I have no idea how to find the desired Attribute and then collect the Nested Elements under that Attribute. This whole process has been very frustrating, and I have a hard time understanding any of the .NET documentation. So I think I'm just going to use a text file. The method in my above comment is basically the same (without knowing how to read subchild elements rather than different attributes), and text requires less formatting.

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.

Thank you again for taking the time to read through and provide an answer. I shall upvote now, and if no-one (i.e. Bunny) leaves any further information, I shall accept and close this question.

avatar image ArkaneX · Dec 17, 2013 at 11:05 AM 0
Share

Sorry alucardj - I thought that you know what to do after reading X$$anonymous$$L. That's why my answer was related just to fixing the error you mentioned.

Assu$$anonymous$$g the wiki code works, calling $$anonymous$$onsterContainer.Load should cause deserialization of the X$$anonymous$$L file content into $$anonymous$$onsterContainer class instance. This means, that all properties of this class, mapped to elements/attributes in X$$anonymous$$L, will be automatically filled with proper values. For example, variable $$anonymous$$onsters should be initialized with two monsters you defined in your X$$anonymous$$L. Variable name of the first monster will be set to EarthDragon, and the second one to FireDragon. Variables health, attack and defense will not be filled automatically though, because they don't match any element in the file. And that's because letter casing is important - your variables are lowercase, while first letter in element names is uppercase. To fix this, you can annotate your variables with proper X$$anonymous$$L attributes, e.g.

 @XmlElement("Health")
 public var health : int;

This way serializer knows that after reading Health element in $$anonymous$$onster element, it should use it to initialize health variable in $$anonymous$$onster class instance. You could of course change name of X$$anonymous$$L element from Health to health as well.

Anyway - now you have your monster collection filled with your dragon data from file. And they're already standard .NET classes, not X$$anonymous$$L data any more, so you can iterate using for or foreach, you can use LINQ, etc.

What I just wrote might be a bit chaotic, but if you have any questions, please let me know. I also suggest reading some xml serialization tutorial, for example this. It is for C#, but translating it to UnityScript should be no problem.

avatar image ArkaneX · Dec 17, 2013 at 11:11 AM 0
Share

Second part of the tutorial I linked is more suitable for your case, but anyway - please read both :)

avatar image AlucardJay · Dec 17, 2013 at 01:19 PM 0
Share

Thank you for the resources. After 2 hours of more frustration, I havn't made any progress, all the while thinking about how my project is now just sitting there when all was going so well.

I shall definitely continue to try and learn from that tutorial, but in the meantime all I need to continue my project is to read a pre-made X$$anonymous$$L file without all the serialization/deserialization.

Would you $$anonymous$$d having a look at my forum post using another method?

This may seem like I'm after the easy way out, and that's partly correct, but your advice was not in vain, I shall continue to try and fathom the serialization/deserialization method.

avatar image AlucardJay · Dec 17, 2013 at 02:11 PM 0
Share

Just to prove I'm not full of s***, I got past all the errors in the example code, and importing namespaces, and got up to Attributes.

From the start, there was something strange going on :

 <?xml version="1.0" encoding="utf-8"?>
 <SomethingIsWrongHere xmlns:xsi="http://www.w3.org/2001/X$$anonymous$$LSchema-instance" xmlns:xsd="http://www.w3.org/2001/X$$anonymous$$LSchema" Number="4">
   <Street>Rohini</Street>
   <CityName>Delhi</CityName>
 </SomethingIsWrongHere>

wtf?!

I couldn't create a list of addresses, I don't know what class/namespace List is supposed to inherit from, but it wouldn't even compile :

 Assets/_Scripts/xmlReader/XmlTutorial_Write.js(54,18): BCE0017: The best overload for the method 'XmlTutorial_Write.Serialize(AddressDetails)' is not compatible with the argument list '(System.Collections.Generic.List.<AddressDetails>)'.

m'kay...

 #pragma strict
 
 import System.Xml.Serialization; // for XmlSerializer
 import System.IO; // for TextWriter/StreamWriter
 
 //import System.Collections.Generic; // to use List ** NOPE !
 // Assets/_Scripts/xmlReader/XmlTutorial_Write.js(54,18): 
 // BCE0017: The best overload for the method 'XmlTutorial_Write.Serialize(AddressDetails)' 
 // is not compatible with the argument list '(System.Collections.Generic.List.<AddressDetails>)'.
 
 
 // simple class that needs to be serialized
 @XmlRoot( "SomethingIsWrongHere" )
 public class AddressDetails
 {
     @XmlAttribute( "Number" )
     public var HouseNo : int;
     
     @XmlElement( "Street" )
     public var StreetName : String;
     
     @XmlElement( "CityName" )
     public var City : String;
     private var PoAddress : String;
 }
 
 
 // Code to serialize the above class
 //public static function $$anonymous$$ain( args : String[] ) 
 public function DoSomething() 
 { 
     /*
     // Part 2
     var AddressList : List.< AddressDetails > = new List.< AddressDetails >();
     
     // address 1
     var detail1 : AddressDetails = new AddressDetails();
     
     detail1.HouseNo = 4;
     detail1.StreetName = "Rohini";
     detail1.City = "Delhi";
     
     // address 2
     var detail2 : AddressDetails = new AddressDetails();
     
     detail2.HouseNo = 55;
     detail2.StreetName = "Perplexed";
     detail2.City = "Confused";
     
     AddressList.Add( detail1 ); 
     AddressList.Add( detail2 ); 
     
     Serialize( AddressList );
     */
     
     /*
     // Part 1
     var details : AddressDetails = new AddressDetails();
     
     details.HouseNo = 4;
     details.StreetName = "Rohini";
     details.City = "Delhi";
     
     Serialize( details );
     */
 }   
 
 public static function Serialize( details : AddressDetails )
 { 
     var serializer : XmlSerializer = new XmlSerializer( AddressDetails ); 
     
     //var writer : TextWriter = new StreamWriter( Application.dataPath + "/$$anonymous$$yXml.xml" ); 
     var writer : StreamWriter = new StreamWriter( Application.dataPath + "/$$anonymous$$yXml_Write.xml" );
     
     serializer.Serialize( writer, details ); 
 }
 
 
 // Lets Run It
 function Start() 
 {
     DoSomething();
 }

I think I learned a little reading the rest, so I shall rewrite my monster.xml and try reading (pt2)

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

19 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

"Root Element Missing: XML Exception" when trying to load data from XML file 2 Answers

XML Serialization issues 0 Answers

loading XML quiz 1 Answer

XML Serialization not working on WebGL 0 Answers

Serialize a class that extends as a serializable class? 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges