无法从XML读取十进制数

时间:2016-03-18 22:47:25

标签: c# xml visual-studio cultureinfo visual-c#-express-2010

我有一个问题,当我尝试读取具有十进制值的XML文件时,如24.5478785 - 它会返回错误:

  

XML文档中存在错误

有人可以建议,为什么会这样?文件中的小数部分如下所示:<interval>22,555555</interval>

我的代码:

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);
        }
    }
}

修改

XML文件: 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>

2 个答案:

答案 0 :(得分:0)

XML序列化程序使用标准格式来序列化/反序列化浮点/日期时间,它实际上并不关心CultureInfo。这个问题是由于线程cultureInfo中的浮点转换。

这可能不是最佳选择,但您可以尝试在序列化之前更改文化信息。

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

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

或者您可以实现自定义序列化程序。这是一篇很好的文章

Injecting XML Serialization for formatting decimal properties

另一种选择是更改ActionsEntry类并实现包装器属性以转换interval并忽略thread's cultureInfo来解决此问题。

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; }
}

答案 1 :(得分:0)

  

您尚未提供Action和ActionsEntry的结构   课程,所以我继续进行以下假设

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; }

    }

然后,在for循环中我尝试了:

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);
}