Search Unity

Simple XML deserialization breaks after Unity Update

Discussion in 'Scripting' started by DonCornholio, Apr 5, 2020.

  1. DonCornholio

    DonCornholio

    Joined:
    Feb 27, 2017
    Posts:
    92
    Hi there !

    I was updating my Project from 2018.2 to 2019.3.7 to fix some Problems and it worked pretty well except for one thing - the localization via xml files doesn't work anymore. And i don't really get why.

    Unity throws an error when playing the game:
    XmlElement, XmlText, and XmlAnyElement cannot be used in conjunction with XmlAttribute, XmlAnyAttribute, XmlArray, or XmlArrayItem.
    There was an error reflecting field '_languageSettings'.


    I am pretty sure that this code is the culprit, but i don't understand xml serialization well enough to fix it (yet?). And the programmer who wrote this doesn't work at the company anymore.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Xml;
    4. using System.Xml.Serialization;
    5. using System.Collections.Generic;
    6.  
    7. namespace Localisation
    8. {
    9.  
    10.     public class XMLLocalisation
    11.     {
    12.  
    13.         [XmlType("XMLLocalisationLanguage")]
    14.         public class XMLLocalisationLanguage
    15.         {
    16.  
    17.             [XmlAttribute("id")]
    18.             public string _sID = "xx";
    19.  
    20.             [XmlAttribute("name")]
    21.             public string _sName = "default";
    22.          
    23.             [XmlElement("LanguageItem")]
    24.             [XmlArrayItem("LanguageItem")]
    25.             public List<XMLLanguageItem> _languageSettings;
    26.  
    27.             public void print()
    28.             {
    29.                 string output = "";
    30.                 output += _sID + " | " + _sName + "\n";
    31.                 output += "_languageSettings: " + _languageSettings.Count + "\n";
    32.                 foreach (XMLLanguageItem ls in _languageSettings)
    33.                 {
    34.                     output += "\t" + ls._sID + " -> " + ls._sText + "\n";
    35.                 }
    36.                 Debug.Log(output);
    37.             }
    38.  
    39.             public void Initialize()
    40.             {
    41.                 _languageSettings = new List<XMLLanguageItem>();
    42.             }
    43.  
    44.             public void Merge(XMLLocalisationLanguage language, bool overwriteInfo, bool overwriteData)
    45.             {
    46.  
    47.                 if (_sID != language._sID)
    48.                     return;
    49.  
    50.                 if (overwriteInfo)
    51.                 {
    52.                     _sName = language._sName;
    53.                 }
    54.  
    55.                 foreach (XMLLanguageItem item in language._languageSettings)
    56.                 {
    57.                     XMLLanguageItem itemOrg = null;
    58.                     foreach (XMLLanguageItem item2 in _languageSettings)
    59.                     {
    60.                         if (item._sID == item2._sID)
    61.                         {
    62.                             itemOrg = item2;
    63.                             break;
    64.                         }
    65.                     }
    66.                     if (itemOrg != null)
    67.                     {
    68.                         if (overwriteData)
    69.                             itemOrg._sText = item._sText;
    70.                     }
    71.                     else
    72.                     {
    73.                         XMLLanguageItem xmlItem = new XMLLanguageItem();
    74.                         xmlItem._sID = item._sID;
    75.                         xmlItem._sText = item._sText;
    76.                         _languageSettings.Add(xmlItem);
    77.                     }
    78.                 }
    79.              
    80.             }
    81.  
    82.             public void ApplySpecialChars()
    83.             {
    84.                 foreach (XMLLanguageItem item in _languageSettings)
    85.                 {
    86.                     string text = item._sText;
    87.  
    88.                     text = text.Replace("\\n", "\n");
    89.  
    90.                     item._sText = text;
    91.                 }
    92.             }
    93.  
    94.         }
    95.  
    96.  
    97.  
    98.         [XmlType("XMLLanguageItem")]
    99.         public class XMLLanguageItem
    100.         {
    101.             [XmlAttribute("id")]
    102.             public string _sID = "";
    103.  
    104.             [XmlText]
    105.             public string _sText = "";
    106.         }
    107.  
    108.  
    109.     }
    110.  
    111. }
    If someone can help me or at least point me into the right direction, i'd be really glad. I am already a little late on the release
     
    Last edited: Apr 5, 2020
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,736
    Reverse the XML process and make a test script that writes a text file containing one of these objects out using XML.

    Now pull up your text editor and see how different the data shape is from your actual data files that are failing to load.

    You might gain some intel from that comparison.

    And if you need to reshape the data, while you're at it, get rid of the XML and use JSON.

    I quote many very sage programmers:

    "Let's say you have a problem and decide to use XML. Now you have two problems."
     
  3. DonCornholio

    DonCornholio

    Joined:
    Feb 27, 2017
    Posts:
    92
    Thanky you very much for those tipps! Serializing the existing structure is a really good idea. This was basically my first time dealing with serialization & xml - normally i 3d model or write shader code or node based procedural stuff. I just fixed it after scratching my head about it for more than 2 days! I used this guide https://forum.unity.com/threads/saving-and-loading-data-xmlserializer.85925/ and checked the smiliarities to my setup and then tried to match the guide's example as closely as possible.

    For anyone having a similiar problem, this is the working code:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Xml;
    4. using System.Xml.Serialization;
    5. using System.Collections.Generic;
    6.  
    7. namespace Localisation
    8. {
    9.  
    10.     public class XMLLocalisation
    11.     {
    12.  
    13.         [XmlRoot("XMLLocalisationLanguage")]
    14.         public class XMLLocalisationLanguage
    15.         {
    16.  
    17.             [XmlAttribute("id")]
    18.             public string _sID = "xx";
    19.  
    20.             [XmlAttribute("name")]
    21.             public string _sName = "default";
    22.  
    23.             //[XmlArray("LanguageItems")]
    24.             //[XmlArrayItem("LanguageItem")]
    25.  
    26.  
    27.             [XmlArray("LanguageItems"), XmlArrayItem("LanguageItem")]
    28.             //[XmlAttribute("LanguageItem")]
    29.             //[XmlArray("LanguageItem")]
    30.             //[XmlArray("LanguageItem")]
    31.  
    32.             public List<XMLLanguageItem> _languageSettings;
    33.  
    34.             public void print()
    35.             {
    36.                 string output = "";
    37.                 output += _sID + " | " + _sName + "\n";
    38.                 output += "_languageSettings: " + _languageSettings.Count + "\n";
    39.                 foreach (XMLLanguageItem ls in _languageSettings)
    40.                 {
    41.                     output += "\t" + ls._sID + " -> " + ls._sText + "\n";
    42.                 }
    43.  
    44.                 Debug.Log(output);
    45.             }
    46.  
    47.             public void Initialize()
    48.             {
    49.                 _languageSettings = new List<XMLLanguageItem>();
    50.             }
    51.  
    52.             public void Merge(XMLLocalisationLanguage language, bool overwriteInfo, bool overwriteData)
    53.             {
    54.  
    55.                 if (_sID != language._sID)
    56.                     return;
    57.  
    58.                 if (overwriteInfo)
    59.                 {
    60.                     _sName = language._sName;
    61.                 }
    62.  
    63.                 foreach (XMLLanguageItem item in language._languageSettings)
    64.                 {
    65.                     XMLLanguageItem itemOrg = null;
    66.                     foreach (XMLLanguageItem item2 in _languageSettings)
    67.                     {
    68.                         if (item._sID == item2._sID)
    69.                         {
    70.                             itemOrg = item2;
    71.                             break;
    72.                         }
    73.                     }
    74.                     if (itemOrg != null)
    75.                     {
    76.                         if (overwriteData)
    77.                             itemOrg._sText = item._sText;
    78.                     }
    79.                     else
    80.                     {
    81. #if DEBUG_LOCALIZATION
    82.                         Debug.LogError("Merging Language Items in " + item._sID + " " + item._sText);
    83. #endif
    84.                         XMLLanguageItem xmlItem = new XMLLanguageItem();
    85.                         xmlItem._sID = item._sID;
    86.                         xmlItem._sText = item._sText;
    87.                         _languageSettings.Add(xmlItem);
    88.                     }
    89.                 }
    90.                
    91.             }
    92.  
    93.             public void ApplySpecialChars()
    94.             {
    95.                 foreach (XMLLanguageItem item in _languageSettings)
    96.                 {
    97.                     string text = item._sText;
    98.  
    99.                     text = text.Replace("\\n", "\n");
    100. #if DEBUG_LOCALIZATION
    101.                     Debug.LogError("ApplySpecialChars()" + text + " " + item._sText);
    102. #endif
    103.                     item._sText = text;
    104.                 }
    105.             }
    106.  
    107.         }
    108.  
    109.  
    110.  
    111.         [XmlType("XMLLanguageItem")]
    112.         public class XMLLanguageItem
    113.         {
    114.             [XmlAttribute("id")]
    115.             public string _sID = "";
    116.  
    117.             //[XmlText]
    118.             //public string _sText = "";
    119.  
    120.             //[XmlAttribute("text")]
    121.             //public string _sText = "";
    122.  
    123.             [XmlText]
    124.             public string _sText = "";
    125.  
    126.             public void print()
    127.             {
    128.  
    129. #if DEBUG_LOCALIZATION
    130.                 Debug.LogError("XMLLanguageItem : " + _sID + "  " + _sText);
    131. #endif
    132.  
    133.             }
    134.         }
    135.  
    136.  
    137.     }
    138.  
    139. }
     
  4. DonCornholio

    DonCornholio

    Joined:
    Feb 27, 2017
    Posts:
    92
    The thing i still don't understand though:
    Why did the code work before the upgrade of the Unity Version? Isn't the xml stuff dependent on the .net version that is used (which didn't change) ?
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,736
    XML is dependent on the precise alignment of the moon relative to the House of Aquarius.

    Notably, JSON does not have this quirk.