1

I have code that deserializes XMLDocument into an array. But it throws NullReferenceException any time I call it in Xamarin.Forms Android project. After days of debugging I created a .NET Console App, coppied the problematic code into it and lo and behold it works flawlessly. Can anyone help me with this problem ? Here is the XMLDocument i'm working with:

<?xml version="1.0" encoding="utf-8" ?>
<Otazky>
  <Otazka>
    <Typ>ABC</Typ>
    <Bodu>1</Bodu>
    <Ukol> Ve kterém z následujících souvětí není chyba v interpunkci?</Ukol>
    <Moznosti>
      <Moznost>A) Po vyčerpávajících mrazech</Moznost>
      <Moznost>B) Mé obavy se každým dnem stupňovaly,</Moznost>
      <Moznost>C) Pokud snížím množství sladkostí</Moznost>
      <Moznost>D) Rodiče celý víkend usilovně přemýšleli</Moznost>
    </Moznosti>
    <Spravna>C</Spravna>
  </Otazka>

<Otazka>
  <Typ>Vyber</Typ>
  <Bodu>2</Bodu>
  <Ukol> Ukol2 </Ukol>
  <Moznosti>
    <Moznost>A) Po vyčerpávajících mrazech</Moznost>
    <Moznost>B) Mé obavy se každým dnem stupňovaly</Moznost>
    <Moznost>C) Pokud snížím množství sladkostí</Moznost>
    <Moznost>D) Rodiče celý víkend usilovně přemýšleli</Moznost> 
  </Moznosti> 
  <Spravna>D</Spravna>
</Otazka>
</Otazky>

Here are the classes I use to store each Otazka element:

public class Otazka
{
    [XmlElement(ElementName = "Typ")]
    public string Typ { get; set; }
    [XmlElement(ElementName = "Bodu")]
    public int Bodu { get; set; }
    [XmlElement(ElementName = "Ukol")]
    public string Ukol { get; set; }

    [XmlElement(ElementName = "Moznosti")]
    public Moznosti Moznosti { get; set; }
    [XmlElement(ElementName = "Spravna")]
    public string Spravna { get; set; }
}

[XmlRoot(ElementName = "Otazky")]
public class Otazky
{
    [XmlElement(ElementName = "Otazka")]
    public List<Otazka> Otazka { get; set; }
}

And finally the code that deserializes the XML into my class:

Otazka[] LoadXMLData()
{
                using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("DDKTCKE_APP.MyResources.Otazky.xml"))
                {
                    XDocument doc = XDocument.Load(stream);

                    var result = from q in doc.Descendants("Otazka")
                             select new Otazka
                             {
                                 Typ = q.Element("Typ").Value,
                                 Bodu = Convert.ToInt32(q.Element("Bodu").Value),
                                 Ukol = q.Element("Ukol").Value,
                                 Moznosti = new Moznosti(q.Element("Moznosti").Elements().Select(x => x.Value).ToList()),                                                            
                                 Spravna = q.Element("Spravna").Value
                             };

                    return result.ToArray();

                }
}

The NullReferenceException is thrown in the line that returns results.ToArray(). Also when i enclosed the whole function in a Try...Catch block it didn't catch anything.

Adream
  • 49
  • 5

2 Answers2

1

The xml contains unicode characters while the ident (first line) say utf-8. So you need to skip the ident line so there isn't a conflict. See code below :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            Otazka[] otazka = LoadXMLData(FILENAME);
        }
        static Otazka[] LoadXMLData(string filename)
        {
            using (var stream = File.OpenRead(filename))
            {
                StreamReader reader = new StreamReader(stream);
                reader.ReadLine();  //read line to skip xml identification line which is utf-8
                                    //file contains unicode characters
                XDocument doc = XDocument.Load(reader);

                //_Counter = doc.ToString().Length;


                var result = (from q in doc.Descendants("Otazka")
                             select new Otazka
                             {
                                 Typ = q.Element("Typ").Value,
                                 Bodu = Convert.ToInt32(q.Element("Bodu").Value),
                                 Ukol = q.Element("Ukol").Value,
                                 //Moznosti = new Moznosti(q.Element("Moznosti").Elements().Select(x => x.Value).ToList()),
                                 Spravna = q.Element("Spravna").Value
                             }).ToArray();

                return result;

            }
        }
    }

    public class Otazka
    {
        [XmlElement(ElementName = "Typ")]
        public string Typ { get; set; }
        [XmlElement(ElementName = "Bodu")]
        public int Bodu { get; set; }
        [XmlElement(ElementName = "Ukol")]
        public string Ukol { get; set; }

        //[XmlElement(ElementName = "Moznosti")]
        //public Moznosti Moznosti { get; set; }
        [XmlElement(ElementName = "Spravna")]
        public string Spravna { get; set; }
    }

    [XmlRoot(ElementName = "Otazky")]
    public class Otazky
    {
        [XmlElement(ElementName = "Otazka")]
        public List<Otazka> Otazka { get; set; }
    }
}
jdweng
  • 33,250
  • 2
  • 15
  • 20
  • I don't think I'm using any characters that are not present in UTF-8. All the diacritics are supported by this encoding. Your solution sadly doesn't fix anything, I'm still getting the same error. Although commenting out the Moznosti variable, like you did, makes it run wtihout any errors. So atleast I know the problem is with deserializing the List Moznosti. – Adream Nov 17 '19 at 12:20
  • Open notepad and paste xml. Then use File:SaveAs and select encoding utf-8. Then save. You will get a warning that code contains unicode characters. – jdweng Nov 17 '19 at 14:17
-1

I created a new empty Xamarin.Forms project (same way as before), copied all the code from the old one into it. And it works.

Adriaan
  • 17,741
  • 7
  • 42
  • 75
Adream
  • 49
  • 5
  • Please mention your frustration in a polite way, and steer clear of obscenities in your posts here. They will be caught on quickly and can lead to lots of downvotes and possible bans for behaviour. – Adriaan Nov 18 '19 at 14:38
  • 1
    Better yet - don't mention frustration at all as it's noise (not relevant to the answer). – TylerH Nov 18 '19 at 14:45
  • 1
    In that case maybe there was a wrong or missing [byte order mark](https://en.wikipedia.org/wiki/Byte_order_mark) in the old project's resource file. See: [Specify encoding when reading file from Resource](https://stackoverflow.com/q/39790293), – dbc Nov 18 '19 at 17:24