My game needs a dialogue system and trough research I found that using a XML to format the dialogues is the best approach to create a “script” for the game. I made this XML:
<script>
<dialogue>
<id>1</id>
<speaker>renata</speaker>
<speech>blablablabla</speech>
<duration>3</duration>
<option_1>yes</option_1>
<option_2>maybe</option_2>
<option_3>no</option_3>
</dialogue>
</script>
I know it’s not very good, but the person who is writing the script don’t know how to use XML, so I did a Google Sheet and after I will convert it to a CSV and XML.
And my dialogue “logic” will be:
Every NPC has an “dialogue range”, which will tell the game where the dialogue begins and ends, so I need to read the ID of the lines.
So I tried to parse the XML into a list, but i can’t get only a single element of the XML (like “id”)
var rows = XDocument.Load("script.xml")
.Root.Elements()
.Select(row => row.Value).ToList();
My question is:
Which structure is the best for me to parse the XML, so I can get the element ID of the lines instead of a unique string?
I highly recommand you to use another method to manage XML files. The .Net framework proposes a very simple way to do that using xmlserializer.
You just have to define a class (which does not inherit from MonoBehaviour since it’s just a data container)
Take a look at a function I made for a project. One is for serialization (save into an XML file), the other for deserialization (extract from file)
// ====================================================================================================
/// <summary>
/// Serializes the sculpture to store the data into an xml file.
/// </summary>
public void SerializeSculpture()
{
XmlSerializer serializer = new XmlSerializer( typeof( C_Sculpture ) );
System.IO.StreamWriter streamWriter = System.IO.File.CreateText( pathToResources + "/data.xml" ) ;
// scultureData is type of C_Sculpture
serializer.Serialize( streamWriter, sculptureData );
streamWriter.Close() ;
streamWriter.Dispose() ;
}
// ====================================================================================================
/// <summary>
/// Deserializes the sculpture if an xml file exists.
/// </summary>
public void DeserializeSculpture()
{
System.IO.FileStream fileStream ;
XmlReader reader ;
XmlSerializer serializer = new XmlSerializer( typeof( C_Sculpture ) );
// Check if file exists before opening a stream reader on it
if( !System.IO.File.Exists( pathToResources + "/data.xml" ) )
{
fileStream = System.IO.File.Create( pathToResources + "/data.xml" ) ;
fileStream.Close() ;
fileStream.Dispose() ;
SerializeSculpture() ;
}
else
{
// Open the data file and read it so as to fill the sculptureData structure
fileStream = new System.IO.FileStream( pathToResources + "/data.xml", System.IO.FileMode.Open );
reader = new XmlTextReader(fileStream) ;
try
{
if( serializer.CanDeserialize( reader ) )
sculptureData = serializer.Deserialize( reader ) as C_Sculpture;
}
finally
{
// Don't forget to close the readers and streams !
reader.Close() ;
fileStream.Close() ;
fileStream.Dispose() ;
}
}
}
For your case, you can define the a C_Dialogue class as follow :
using System.Collections;
using System.Collections.Generic;
using System.Xml.Serialization;
[XmlRoot("Dialogue")]
public class C_Dialogue
{
/* ======================================== *\
* ATTRIBUTES *
\* ======================================== */
/// <summary>
/// Gets or sets the identifier.
/// </summary>
/// <value>The identifier.</value>
[XmlAttribute]
public int Id
{
get ;
private set;
}
/// <summary>
/// Gets or sets the speaker.
/// </summary>
/// <value>The speaker.</value>
public string Speaker
{
get ;
set ;
}
/// <summary>
/// Gets or sets the speech.
/// </summary>
/// <value>The speech.</value>
public string Speech
{
get ;
set ;
}
/// <summary>
/// Gets or sets the duration.
/// </summary>
/// <value>The long description.</value>
public float Duration
{
get ;
set ;
}
/// <summary>
/// Gets or sets the options.
/// </summary>
/// <value>The options.</value>
[XmlArray("Options")]
[XmlArrayItem("Option")]
public List<string> Options
{
get ;
set ;
}
// ====================================================================================================
/// <summary>
/// Initializes a new instance of the C_Dialogue class.
/// </summary>
// YOU MUST DEFINE A CONSTRUCTOR WITHOUT ANY ARGUMENT
public C_Dialogue( )
{
// Set default value here
}
// You can define other constructors if you want too
public C_Dialogue( int id )
{
Id = id ;
}
}