- Home /
Help with XML reading and writing
Hi all, hope you can help me out, the line wordLists = serializer.Deserialize(stream) as WordLists;
, is getting the error:
InvalidOperationException: was not expected System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadRoot (System.Xml.Serialization.XmlTypeMapping rootMap) System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadRoot () System.Xml.Serialization.XmlSerializer.Deserialize (System.Xml.Serialization.XmlSerializationReader reader) Rethrow as InvalidOperationException: There is an error in XML document. System.Xml.Serialization.XmlSerializer.Deserialize (System.Xml.Serialization.XmlSerializationReader reader) System.Xml.Serialization.XmlSerializer.Deserialize (System.Xml.XmlReader xmlReader) System.Xml.Serialization.XmlSerializer.Deserialize (System.IO.Stream stream) CreateWordList.AddWordListToList () (at Assets/scripts/XML/CreateWordList.cs:59) CreateWordList.AddWordList () (at Assets/scripts/XML/CreateWordList.cs:38) UnityEngine.Events.InvokableCall.Invoke () (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:165) UnityEngine.Events.UnityEvent.Invoke () (at C:/buildslave/unity/build/Runtime/Export/UnityEvent_0.cs:58) UnityEngine.UI.Button.Press () (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:36) UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:45) UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, >UnityEngine.EventSystems.BaseEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:50) UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, >UnityEngine.EventSystems.EventFunction`1 functor) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:261) UnityEngine.EventSystems.EventSystem:Update()
Heres my code:
public void AddWordListToList()
{
XmlSerializer serializer = new XmlSerializer(typeof(WordLists));
string filename2 = Application.dataPath + "/StreamingAssets/WordLists/wordlists.xml";
FileStream stream = new FileStream(filename2, FileMode.Open);
wordLists = serializer.Deserialize(stream) as WordLists;
stream.Close();
//wordLists.list.Add(WordlistName);
foreach(WordListData data in wordLists.list)
{
print(WordlistName);
}
using(StreamWriter writer = new StreamWriter(filename2))
{
serializer.Serialize(writer, wordLists.list);
}
}
// ...
[System.Serializable]
public class WordListData
{
public string WordListName;
}
[System.Serializable]
public class WordLists
{
public List<WordListData> list = new List<WordListData>();
}
I hope someone can help please, Many Thanks Tekman
You seem to have an error inside the X$$anonymous$$L file. Can you provide it?
<?xml version="1.0" encoding="utf-8"?>
<list>
<list>
<WordlistName>grwew</WordlistName>
<WordlistName>gsrhst</WordlistName>
<WordlistName>grwufew</WordlistName>
<WordlistName>grwrtew</WordlistName>
<WordlistName>gmuryrwew</WordlistName>
<WordlistName>grwew</WordlistName>
<WordlistName>gsghdrhst</WordlistName>
<WordlistName>gsrhst</WordlistName>
<WordlistName>gsrsthst</WordlistName>
<WordlistName>gsrsghdhst</WordlistName>
</list>
</list>
Answer by Flokky_ · Oct 18, 2017 at 03:31 PM
The first thing is: are you sure you've got correct data in file "/StreamingAssets/WordLists/wordlists.xml"?
And try to make your WordListData class as:
[System.Serializable]
public class WordListData
{
public string WordListName {get;set;}
public WordListData() { }
}
P.S. Why do you creating WordLists class with just one field of List? It is no sence to do so. Just serialize and deserialize a list without wrapping it in class.
TBH i dont really know what im doing and im not surprised that most of it is wrong. Basically i am trying to store a list into an xml file which can then be read, and more things added to the list and then written to the file again. If you could help me with this it would make my day.
By the way, always wrap your unmanaged resources such as FileStream instance with using:
using(FileStream fs = new FileStream(...))
{
//some code here
}
thanks, but could you help me fully do it, it would be really helpful
What kind of resources you want to have? Should it be a single static resource (list) that is acceptible at any part of your game/programm?
Look, it is bad idea to load your list from file each time you need add or read data to/from it. It is just waste of memory and time.
Here is an example how to implement your idea:
class TextData
{
string path;
bool autoSave;
List<string> lines;
public List<string> Lines
{
get { return lines; }
}
public void AddLine(string line)
{
lines.Add(line);
if(autoSave)
{
Save();
}
}
public void Save()
{
XmlSerializer serializer = new XmlSerializer(typeof(List<string>));
using (FileStream fs = new FileStream(path, File$$anonymous$$ode.OpenOrCreate))
{
serializer.Serialize(fs, lines);
}
}
void Load()
{
XmlSerializer serializer = new XmlSerializer(typeof(List<string>));
using (FileStream fs = new FileStream(path, File$$anonymous$$ode.OpenOrCreate))
{
if (fs.Length > 0)
{
lines = (List<string>)serializer.Deserialize(fs) ?? new List<string>();
}
else
{
lines = new List<string>();
}
}
}
public TextData(string path, bool autoSaveOnChange = true)
{
this.path = path;
autoSave = autoSaveOnChange;
Load();
}
}
Also it can be used for other types, not only for string, if to change type of data wich is stored in the list.
Thanks, I’ll try this. The reason i am trying to load the file every time is that it is likely that the file will only need to be loaded averagely once per game run.
As for me, it's good idea to write code "for future". So if in future you'll need to use this list more than once per game, you can be sure it will be optimized already for multiple using. And it'll be less work to do to make it suitable for the new purpose.