C# (CSharp/.cs) 7.0
.NET Framework 4.7.2
I'm making a Localization system for a mod (based on the game's language), so I used an XML file to store translations, which look like this :
<?xml version="1.0" encoding="utf-16" ?>
<LocalizationPackages>
<LocalizationPackage Lang="English">
<Text key="Ency_PrawnLaserArm">Prawn Laser module</Text>
<Text key="EncyDesc_PrawnLaserArm">Description</Text>
<Text key="EncyPath_Weaponry">Weaponry</Text>
<Text key="ExplosiveTorpedoItemName">Explosive torpedo</Text>
<Text key="ExplosiveTorpedoItemTooltip">A new lethal weapon designed by Alterra© for missions on 4546B after the result of previous Alterra© missions.</Text>
</LocalizationPackage>
<LocalizationPackage Lang="French">
<Text key="Ency_PrawnLaserArm">Module laser pour Prawn</Text>
<Text key="EncyDesc_PrawnLaserArm">Description</Text>
<Text key="EncyPath_Weaponry">Armement</Text>
<Text key="ExplosiveTorpedoItemName">Torpille explosive</Text>
<Text key="ExplosiveTorpedoItemTooltip">Une nouvelle arme létale designée par Alterra® pour les missions sur 4546B après le résultat de la mission Alterra précédente sur la planète.</Text>
</LocalizationPackage>
</LocalizationPackages>
However, while reading the XML file with my own system based on what I saw on the Microsoft Documentation, it returns a totally empty object.
using System.Linq;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Reflection;
using SMLHelper.V2.Handlers;
using Logger = QModManager.Utility.Logger;
namespace VELDsAlterraWeaponry
{
namespace LocalizationHandler
{
[XmlRoot("LocalizationPackages")]
public class LocalizationPackages
{
[XmlArray("LocalizationPackage")]
public LocalizationPackage[] Localizations;
}
/// <summary>
/// LocalizationPackage is a Localization Package ref -
/// </summary>
public class LocalizationPackage
{
[XmlAttribute("Lang")]
public string Lang;
[XmlArray("Text")]
public Text[] Texts;
}
public class Text
{
[XmlAttribute]
public string key;
public string value;
}
}
class LanguagesHandler
{
// This is the path to my mod directory, this is the default schema for this modloader.
private static string ModPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
// This is the filename of my Localizations file
private static string filename = "Localizations.xml";
// This is the function that patch the language through the game, but we do not care about this.
public static void LanguagePatch()
{
Logger.Log(Logger.Level.Info, "Starting patching the languages !");
XmlSerializer serializer = new XmlSerializer(typeof(LocalizationHandler.LocalizationPackages));
FileStream fs = new FileStream(Path.Combine(ModPath, filename), FileMode.Open);
// My LocalizationPackage, that SHOULD be read and set by the definition some lines under...
LocalizationHandler.LocalizationPackages lps;
// This logs the current language of the game (prints "French" for me)
Logger.Log(Logger.Level.Info, Language.main.GetCurrentLanguage());
// Redefines normally the lps with the datas of the XML ?
lps = (LocalizationHandler.LocalizationPackages)serializer.Deserialize(fs);
// Have to log each Localization Lang name
foreach (LocalizationHandler.LocalizationPackage lockalizationpack in lps.Localizations) Logger.Log(Logger.Level.Info, lockalizationpack.Lang);
Logger.Log(Logger.Level.Info, "All LPs logged.");
// Have to set each label in game with the value of the XML.
// Do not care too lot about that, it's mainly managed by the SMLHelper lib.
foreach(LocalizationHandler.Text text in lps.Localizations.Single(lp => lps.Localizations.Any(lp1 => lp1.Lang == Language.main.GetCurrentLanguage()) ? lp.Lang == Language.main.GetCurrentLanguage() : lp.Lang == Language.defaultLanguage).Texts)
{
Logger.Log(Logger.Level.Info, $"Checking string, key {text.key}");
if (Language.main.Get(text.key) != null)
{
LanguageHandler.SetLanguageLine(text.key, text.value);
Logger.Log(Logger.Level.Info, $"Patched key {text.key} with text '{(text.value.Length > 50 ? text.value.Substring(50) : text.value)}'");
}
else
{
Logger.Log(Logger.Level.Warn, $"Key {text.key} does not reference any key in game. Please check the case.");
}
}
Logger.Log(Logger.Level.Info, "Language patching done.");
}
}
}
And when I try logging all the LocalizationPackages, it does not log anything, and immediately print "All LPs logged.". (foreach (LocalizationHandler.LocalizationPackage lockalizationpack in lps.Localizations) Logger.Log(Logger.Level.Info, lockalizationpack.Lang);
)
So, where's my error ? Did I did something wrong with my classes ? My reading system is obsolete ?
(please don't be rude, I'm a very beginner in C#, I started 5 days ago C# with this project)
CodePudding user response:
Code below works. [XmlArray] expect two levels of tags . So use [XmlElement] when you have only one level of tags. Also added [XmlText]
using System;
using System.Linq;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApp2
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
StreamReader reader = new StreamReader(FILENAME);
reader.ReadLine(); //skip utf-16
XmlSerializer serializer = new XmlSerializer(typeof(LocalizationPackages));
LocalizationPackages packages = (LocalizationPackages)serializer.Deserialize(reader);
}
}
[XmlRoot("LocalizationPackages")]
public class LocalizationPackages
{
[XmlElement("LocalizationPackage")]
public LocalizationPackage[] Localizations;
}
public class LocalizationPackage
{
[XmlAttribute("Lang")]
public string Lang;
[XmlElement("Text")]
public Text[] Texts;
}
public class Text
{
[XmlAttribute]
public string key;
[XmlText]
public string value;
}
}