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 /
This post has been wikified, any user with enough reputation can edit it.
avatar image
0
Question by V4mpy · Oct 17, 2013 at 03:44 PM · arraysizexmlinitialize

Parsing XML - appropriate array size

Hello,

I have a XML-File like this:

 <?xml version="1.0" encoding="UTF-8"?>
 <dialogs>
       <dialog id="2">
         <npcText>Hallo, ich bin Melissa</npcText>
         <option id = "0">
           <optionText>Hallo.</optionText>
           <link>3</link>
         </option>
         <option id = "1">
           <optionText>End</optionText>
           <link>9999</link>
         </option>    
       </dialog>
         
           <dialog id="3">
         <npcText>Schön dich in dieser Stadt zu sehen.</npcText>
         <option id = "0">
           <optionText>Ich schaue mich mal um</optionText>
           <link>9999</link>
         </option>    
       </dialog>
 </dialogs>

My arrays:

 DialogNode[] dialogs; // store all dialogs 
 int[] dialogOptions;  // this should store the amount of options for each dialog

I can parse them, my DialogManager works with them. This is all fine. And IF I'm preset the size of the arrays (dialog and options array), it work's fine too.

My Problem: I want find the appropiate size of both arrays, which I'm need.

My approach:

Read the XML-File and count all dialogs (assumed in my is a amount of options). Read the XML-File again and read amount of options and store them in my second array (size of array is set by amount of dialogs)

 dialogs = new DialogNode[dialogCount];
         for(int i = 0; i < dialogCount; i++){
             dialogs[i] = new DialogNode();
             dialogs[i].options = new Option[optionsCount[i]];
             for(int x = 0; x < optionsCount[i];x++){
                 dialogs[i].options[x] = new Option();
             }
         }


After this, read the xml-file again and store all data in the right variable of the array. Sorry, is my idea bad?

I don't want to parse the XML more than one time. I want to store all stuff, what I need in this XML.

And in don't want to preset my amount of dialogs and my amount of options for each dialog in the inspector.

Greetings,

V4mpy

Comment
Add comment
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

3 Replies

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

Answer by whydoidoit · Oct 17, 2013 at 05:21 PM

You could just use the XML serializer which handles this stuff for you, here is a helper class:

 using UnityEngine;
 using System.Collections;
 using System.Xml.Serialization;
 using System.IO;
 using System.Text;
 using System;
 
 public static class XmlSupport 
 {
     public static T DeserializeXml<T> (this string xml) where T : class
     {
         if( xml != null ) {
             var s = new XmlSerializer (typeof(T));
             using (var m = new MemoryStream (Encoding.UTF8.GetBytes (xml)))
             {
                 return (T)s.Deserialize (m);
             } 
         }
         return null;
     }
     
     public static object DeserializeXml(this string xml, Type tp) 
     {
         var s = new XmlSerializer (tp);
         using (var m = new MemoryStream (Encoding.UTF8.GetBytes (xml)))
         {
             return s.Deserialize (m);
         }
     }
 
     
     public static string SerializeXml (this object item)
     {
         var s = new XmlSerializer (item.GetType ());
         using (var m = new MemoryStream())
         {
             s.Serialize (m, item);
             m.Flush ();
             return Encoding.UTF8.GetString (m.GetBuffer ());
         }
         
         
     }
     
 }

Then you mark up your classes, here's an example of mine:

 using System;
 using System.Xml.Serialization;

  [Serializable]
 [XmlRoot("response")]
 public class HighScoreResult
 {
     public static HighScoreResult Create(string xml)
     {
         return xml.DeserializeXml<HighScoreResult>();
     }
     
     public class HighScoreEntry
     {
         [XmlElement]
         public int position;
         [XmlElement]
         public int score;
         [XmlElement("screenname")]
         public string playerName = "";
     }
     
     public class HighScoreTableResult
     {
         [XmlElement]
         public string name;
         [XmlElement]
         public int position;
         [XmlElement]
         public int score;
         
         [XmlArray("highscoreentries")]
         [XmlArrayItem("highscoreentry")]
         public HighScoreEntry[] highscoreentries = new HighScoreEntry[0];
     }
     
     public class HighScore
     {
         [XmlArray("highscoretables")]
         [XmlArrayItem("highscoretable")]
         public HighScoreTableResult[] highscoretables = new HighScoreTableResult[0];
     }
     
     [XmlElement]
     public HighScore highscore;
     
 }

Then you deserialize one like this:

    var result = someXmlString.DeserializeXml<HighScoreResult>();

And serialize it using:

    var xml = someXmlSerializableObject.SerializeXml();
Comment
Add comment · Show 7 · 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 V4mpy · Oct 17, 2013 at 05:38 PM 0
Share

Sorry, i don't get this. I'm not familiar with X$$anonymous$$L and Serialization. Is there a easier way to do this? I don't know how to handle with my options (Option) for each Dialog. It sound, weird, but I'm confused.

avatar image whydoidoit · Oct 17, 2013 at 05:40 PM 0
Share

Sure I'll knock one up for you

avatar image whydoidoit · Oct 17, 2013 at 06:00 PM 0
Share

Ok so here you go (I had to remove the UTF-8 encoding in the start because Unity doesn't like it much):

 using System;
 using UnityEngine;
 using System.Collections;
 using System.Xml;
 using System.Xml.Serialization;
 
 
 public class XmlParseDialogs : $$anonymous$$onoBehaviour
 {
     public string xml=@"<?xml version=""1.0""?>
 <dialogs>
 <dialog id=""2"">
 <npcText>Hallo, ich bin $$anonymous$$elissa</npcText>
 <option id = ""0"">
 <optionText>Hallo.</optionText>
 <link>3</link>
 </option>
 <option id = ""1"">
 <optionText>End</optionText>
 <link>9999</link>
 </option>   
 </dialog>
 
 <dialog id=""3"">
 <npcText>Schön dich in dieser Stadt zu sehen.</npcText>
 <option id = ""0"">
 <optionText>Ich schaue mich mal um</optionText>
 <link>9999</link>
 </option>   
 </dialog>
 </dialogs>";
 
     [Serializable]
     [XmlRoot ("dialogs")]
     public class Dialogs
     {
         [XmlElement("dialog")]
         public Dialog[] dialogs;
     }
 
     [Serializable]
     public class Dialog
     {
         [XmlAttribute]
         public int id;
         [XmlElement]
         public string npcText;
         [XmlElement("option")]
         public Option[] options;
     }
 
     public class Option
     {
         [XmlAttribute]
         public int id;
         [XmlElement]
         public string optionText;
         [XmlElement]
         public int link;
     }
     // Use this for initialization
     void Start ()
     {
         var dialogs = xml.DeserializeXml<Dialogs>();
         foreach(var d in dialogs.dialogs)
         {
             Debug.Log(d.npcText);
             foreach(var o in d.options)
             {
                 Debug.Log(o.optionText);
             }
         }
     
     }
     
 }
avatar image whydoidoit · Oct 17, 2013 at 06:02 PM 0
Share

It's only double quoted because I embedded it as a verbatim string.

avatar image V4mpy · Oct 17, 2013 at 06:35 PM 0
Share

Can you please explain this for my understanding? I want understand this, please. And yes, it works pretty nice. Big thanks.

Show more comments
avatar image
0
Wiki

Answer by V4mpy · Oct 17, 2013 at 04:05 PM

I have a dirty solution. I don't like this solution, but it is possible in this way. My XML:

 <dialogs countDialogs = "7">
 <temp></temp>    
 <dialogOptionsCount>2</dialogOptionsCount>    
 <dialogOptionsCount>2</dialogOptionsCount>    
 <dialogOptionsCount>2</dialogOptionsCount>    
 <dialogOptionsCount>1</dialogOptionsCount>    
 <dialogOptionsCount>3</dialogOptionsCount>    
 <dialogOptionsCount>1</dialogOptionsCount>    
 <dialogOptionsCount>1</dialogOptionsCount>    


My ManagerScript:

 int counter = 0;
         XmlReader meinReaderFirst = XmlReader.Create (Application.dataPath + "/XML/dialogs.xml");
         while (meinReaderFirst.Read()) {
             
         if (meinReaderFirst.IsStartElement ("dialogs")) {
                 dialogCount = int.Parse(meinReaderFirst.GetAttribute("countDialogs"));
             }
             
         if(meinReaderFirst.IsStartElement("temp")){
                 optionsCount = new int[dialogCount];
             }        
           
         if(meinReaderFirst.IsStartElement("dialogOptionsCount")){
             optionsCount[counter] = int.Parse(meinReaderFirst.ReadString());
             counter++;
         }
         } 
         for(int i = 0; i < counter; i++){
             Debug.Log("" + optionsCount[i]);
         }

Unity debugs:

 2
 2
 2
 1
 3
 1
 1 

Are there any other solutions?

Comment
Add comment · 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
0

Answer by darkhog · Oct 17, 2013 at 04:18 PM

IMO you should use dynamic arrays for that. In pseudo code:

 while (thereisstillsomethingtoreadoutofxml) {
   dialogs.changesize(dialogs.length+1);
   dialogs[dialogs.length-1].something1 = xmlobject.getnode("something1") // putting something1 into dialogs.something1
 }

This way you also decreasing amount of loops to just one as you are reading and increasing array size as needed. Dialogs of course should be arrays of structs that closely mirrors structure of your xml file.

Comment
Add comment · Show 3 · 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 V4mpy · Oct 17, 2013 at 05:04 PM 0
Share

Can you please give an example? (not pseudo code)

$$anonymous$$y array:

 public DialogNode[] dialogs;

and my custom datatype*s*:

 [System.Serializable]
     public class DialogNode
     {
         public int id;
         public string text;
         public Option[] options;
         
         public DialogNode ()
         {
             
             this.id = 0;
             this.text = "";
         }
     }`

 [System.Serializable]
 public class Option
 {

     public string text;
     public int link;

     public Option ()
     {
         this.text = "";
         this.link = 0;
     }    
 
 }

I want a dynamic dialogs (like your way). And additional a dynamic array of options for each dialog.

avatar image billykater · Oct 17, 2013 at 05:07 PM 0
Share

If you now use List ins$$anonymous$$d of Dialog[] as your type (Namespace System.Collections.Generic) you don't even have to have an explicit line for resizing the array. just use

 dialogs.Add(new Option(parseFromXml))

and the list will grow dynamically as needed. The rest of the array syntax will be the same for lists.

avatar image whydoidoit · Oct 17, 2013 at 05:16 PM 0
Share

Have you considered just marking up the class for X$$anonymous$$L Serialization - it then does it all for you...

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

17 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

Related Questions

Arrays or database? 3 Answers

what is good way to refer array in inspector. 1 Answer

GUI Resize Problem 1 Answer

XML parsing problem - array 0 Answers

how to set an array length? 1 Answer


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