0

I have a problem, when I try to read XML file, which has decimal values, like 24.5478785 - it gives back error:

There is error in XML document

Can someone please advise, why is this happening? Decimal part in file looks like: <interval>22,555555</interval>

My code:

private void OpenFileXml(bool runIt, string file)
{
    //Get data from XML file
    XmlSerializer ser = new XmlSerializer(typeof(ActionsEntry));
    using (FileStream fs = System.IO.File.Open(file, FileMode.Open))
    {
        try
        {
            ActionsEntry entry = (ActionsEntry)ser.Deserialize(fs);
            lvActions.Items.Clear();
            foreach (ActionsEntryAction ae in entry.Action)
            {
                string point = ae.X.ToString() + "," + ae.Y.ToString();
                string interval = (ae.interval).ToString("F6");
                ListViewItem lvi = new ListViewItem(new string[] { point, ((ClickType)(ae.Type)).ToString(), interval, ae.Text });
                ActionEntry acion = new ActionEntry(ae.X, ae.Y, ae.Text, ae.interval, (ClickType)(ae.Type));
                lvi.Tag = acion;
                lvActions.Items.Add(lvi);
            }

            if (runIt)
            {
                btnStart.PerformClick();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "Clicer", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}

EDIT

XML file: enter image description here

XML:

<?xml version="1.0" encoding="utf-8"?><ActionsEntry xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Action>
<X>824</X>
<Y>456</Y>
<Text />
<interval>22,555555</interval>
<Type>0</Type>
</Action>
</ActionsEntry>
JustinasT
  • 561
  • 1
  • 8
  • 27
  • Have you tried to change the CultureInfo ? –  Mar 18 '16 at 22:53
  • Don't really have a clue, what is that... – JustinasT Mar 18 '16 at 22:54
  • 2
    Have a look at this question: http://stackoverflow.com/questions/17437946/xml-deserialization-crashes-on-decimal-parse-due-to-formatting I think it has the answer your looking for. –  Mar 18 '16 at 22:55
  • please post your xml instead of a picture – Renuka Deshmukh Mar 18 '16 at 23:03
  • @RenukaDeshmukh Added – JustinasT Mar 18 '16 at 23:13
  • @hbrock Where is he trying to parse the decimal, AFAICS he's just bringing it in as a string (with a `.ToString("F6")`??). – CodingGorilla Mar 18 '16 at 23:23
  • There are likely more errors than caused by using comma as decimal separator (covered by good explanation I used as duplicate), but that should get you started. Side note: using non-standard formatting for numbers (i.e. locale specific) in XML is bad idea - consider using format with dot as decimal separator as recommended for XML. – Alexei Levenkov Mar 19 '16 at 02:44

2 Answers2

0

XML serializer uses a standard format to serialize/deserialize float/date time and it doesn't actually care about CultureInfo. this problem is due to the float conversion in thread's cultureInfo.

this might not be the best option but you can try to change culture info before serialization.

System.Globalization.CultureInfo customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
customCulture.NumberFormat.NumberDecimalSeparator = ",";

System.Threading.Thread.CurrentThread.CurrentCulture = customCulture;

or either you can implement a custom Serializer. here is a nice article

Injecting XML Serialization for formatting decimal properties

another option is to change ActionsEntry class and implement a wrapper property to convert interval and ignore thread's cultureInfo to solve this problem.

public class ActionsEntry
{
    public Action Action { get; set; }
}

public class Action
{
    public int X { get; set; }

    public int Y { get; set; }

    public string Text { get; set; }

    [XmlIgnore]
    public float interval { get; set; }

    private string _intervalString;
    [XmlElement("interval")]
    public string IntervalString
    {
        get
        {
            return _intervalString;
        }
        set
        {
            _intervalString = value;
            if (!string.IsNullOrEmpty(value))
            {
                interval = float.Parse(value, CultureInfo.InvariantCulture);
            }
        }
    }

    public int Type { get; set; }
}
Glorfindel
  • 21,988
  • 13
  • 81
  • 109
esiprogrammer
  • 1,438
  • 1
  • 17
  • 22
0

You have not provided the structure of your Action and ActionsEntry classes, so I went ahead with following assumptions

public class ActionsEntry
    {
        public ActionsEntry() { Actions = new List<Action>(); }
        [XmlElement("Action")]
        public List<Action> Actions { get; set; }

    }

    public class Action
    {
        public int X { get; set; }
        public int Y { get; set; }

        public string Text { get; set; }

        [XmlElement("interval")]
        public string Interval { get; set; }
        public int Type { get; set; }

    }

Then, in the for loop I tried:

ActionsEntry entry = (ActionsEntry)ser.Deserialize(fs);
foreach (var action in entry.Actions)
{
    string interval = action.Interval.Replace(',', '.');
    decimal intvrl = Decimal.Parse(interval);
    Console.WriteLine(intvrl);
}
Renuka Deshmukh
  • 998
  • 9
  • 16