Search Unity

Problem extracting and deserializing XML content from website

Discussion in 'Scripting' started by tataragne, Oct 17, 2019.

  1. tataragne

    tataragne

    Joined:
    Aug 15, 2009
    Posts:
    27
    Hello everyone,
    Our project has to connect to a web page in order to extract the content of an XML file located on that web page, and converting that result into a profile for our players. The connection and extraction process itself works nicely ; I've managed to extract a string containing the xml with that piece of code :

    Code (CSharp):
    1.  
    2.  
    3. public string SendLoginUrl = "the url referencing the xml file"
    4.  
    5. public IEnumerator SendLoginCo (string firstName, string lastName, string birthdate)
    6.     {
    7.         //Debug.Log ("SEND LOGIN CO");
    8.         if (Application.internetReachability != NetworkReachability.NotReachable) {
    9.  
    10.            
    11.  
    12.  
    13.  
    14.             WWWForm post = new WWWForm ();
    15.             post.AddField ("firstName", firstName);
    16.             post.AddField ("lastName", lastName);
    17.             post.AddField ("birthdate", birthdate);
    18.  
    19.  
    20.             using (UnityWebRequest www = UnityWebRequest.Post(SendLoginUrl, post))
    21.             {
    22.                 yield return www.SendWebRequest();
    23.  
    24.                 if (www.isNetworkError || www.isHttpError)
    25.                 {
    26.                     if (CompteurErrorLogin < 3)
    27.                     {
    28.                         CompteurErrorLogin++;
    29.                         StartCoroutine("ReSendLoginCo", post);
    30.                     }
    31.                 }
    32.                 else
    33.                 {
    34.                     //transmission done
    35.                     Debug.Log("Transmission data done");
    36.                     ResponseTraitement(www.downloadHandler.text);
    37.                 }
    38.             }
    39.  
    40.  
    41.         }
    42.         else {
    43.             Debug.Log ("Votre ordinateur n'est pas connecté");
    44.         }
    45.     }

    Now I have to check if that string contains an error, and if it doesn't, send it to the deserialization method :

    Code (CSharp):
    1.  
    2.  
    3.  
    4.     public void ResponseTraitement (string text)
    5.     {
    6.         XmlDocument document = new XmlDocument ();
    7.         document.LoadXml (text);
    8.         Debug.Log (text);
    9.  
    10.         if (document.DocumentElement.Name == "error") {
    11.  
    12.             string code = document.DocumentElement ["code"].InnerText;
    13.             string message = document.DocumentElement ["message"].InnerText;
    14.             Debug.Log (code + " " + message);
    15.  
    16.         }
    17.         else
    18.         {
    19.             CurrentProfil = Profil.LoadFromText (text);
    20.             UpdateData ();
    21.         }
    22.     }
    23.    

    And convert it into a class of type "Profil" that looks like this :

    Code (CSharp):
    1.  
    2. //[System.Serializable]
    3. [XmlRoot("userData")]
    4. public class Profil {
    5.  
    6.     public int uid;
    7.  
    8.     [XmlIgnore]
    9.     public string firstName;
    10.     [XmlElement("firstName")]
    11.     public XmlCDataSection firstNameCDATA
    12.     {
    13.         get
    14.         {
    15.             XmlDocument doc = new XmlDocument();
    16.             return doc.CreateCDataSection(firstName);
    17.         }
    18.         set
    19.         {
    20.             firstName = value.Value;
    21.         }
    22.     }
    23.  
    24.     [XmlIgnore]
    25.     public string lastName;
    26.     [XmlElement("lastName")]
    27.     public XmlCDataSection lastNameCDATA
    28.     {
    29.         get
    30.         {
    31.             XmlDocument doc = new XmlDocument();
    32.             return doc.CreateCDataSection(lastName);
    33.         }
    34.         set
    35.         {
    36.             lastName = value.Value;
    37.         }
    38.     }
    39.  
    40.     //[XmlIgnore]
    41.     //public string birthdate;
    42.     //[XmlElement("birthdate")]
    43.     //public XmlCDataSection birthdateCDATA
    44.     //{
    45.     //    get
    46.     //    {
    47.     //        XmlDocument doc = new XmlDocument();
    48.     //        return doc.CreateCDataSection(birthdate);
    49.     //    }
    50.     //    set
    51.     //    {
    52.     //        birthdate = value.Value;
    53.     //    }
    54.     //}
    55.  
    56.     [XmlArray("checkpoints"), XmlArrayItem("checkpoint")]
    57.     public List<SavedCheckpoint> checkpointsList = new List<SavedCheckpoint>();
    58.  
    59.     [XmlArray("images"), XmlArrayItem("image")]
    60.     public List<SavedScreenshot> screenshostList = new List<SavedScreenshot>();
    61.  
    62.     [XmlIgnore]
    63.     public string avatar;
    64.     [XmlElement("avatar")]
    65.     public XmlCDataSection avatarCDATA
    66.     {
    67.         get
    68.         {
    69.             XmlDocument doc = new XmlDocument();
    70.             return doc.CreateCDataSection(avatar);
    71.         }
    72.         set
    73.         {
    74.             if (value != null)
    75.             {
    76.                 avatar = value.Value;
    77.             }
    78.         }
    79.     }
    80.  
    81.     public int isNew;
    82.  
    83.  
    84.     public Profil()
    85.     {
    86.  
    87.     }
    88.     public static Profil LoadFromText(string text)
    89.     {
    90.  
    91.         //This method returns an InvalidCastException :
    92.  
    93.         XmlSerializer serializer = new XmlSerializer(typeof(Profil));
    94.         Profil p;
    95.  
    96.         StringReader reader = new StringReader(text);
    97.         Debug.Log("READER : " + reader.ReadToEnd());
    98.         p = (Profil)serializer.Deserialize(reader);
    99.         reader.Close();
    100.  
    101.         return p;
    102.  
    103.  
    104.  
    105.     }
    106.    
    107.     //public string avatar;
    108.  
    109. }
    110.  

    the last function of the "Profil" class, LoadFromText(), returns an InvalidCastException each time it reaches the Deserialize() method :

    Code (CSharp):
    1. System.InvalidOperationException: There is an error in XML document (2, 196). ---> System.InvalidCastException: Specified cast is not valid.
    2.  
    What I want to know is, does the error comes from the string "text", or from Deserialize ? i've double checked the format of the string, and I've tried the serialization - deserialization process on a different project with different classes to see if the class itself was the root of the problem, but no. Any idea ?
     
  2. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    There is an error in XML document (2, 196). Look at that position, what's there?
     
  3. tataragne

    tataragne

    Joined:
    Aug 15, 2009
    Posts:
    27
    I've already compared the XML output to what I was supposed to have mulitple times ; both strings seem to be the same. I used the Trim() method to remove all control characters in case that was the problem, which only caused the error to go from position (3, 1) to (2, 196)
     
  4. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    So what is at those positions? If you say (3,1) and (2,196) I would assume error in xml structure itself and suggest to check it with some online xml validator, there are plenty. Also if you have example file what works then you can diff them and see what is wrong.
     
  5. tataragne

    tataragne

    Joined:
    Aug 15, 2009
    Posts:
    27
    I already tried injecting the xml code into an xml file and using it directly instead of the string, but it didn't work. I didn't know about the xml online validator, I'm gonna check it out. Thanks for the help.