Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 解析Xml文档中的指数值_C# - Fatal编程技术网

C# 解析Xml文档中的指数值

C# 解析Xml文档中的指数值,c#,C#,反序列化对象(我无法修改)时出现问题。 对于某些xml元素,我收到一个指数值,对于在类中表示它们,我使用了十进制值,当我反序列化xml文档时,它会失败 <fwdRate>-9.72316862724032E-05</fwdRate> 按要求 using System; using System.IO; using System.Xml.Serialization; [XmlRoot(ElementName = "result")] public class Resul

反序列化对象(我无法修改)时出现问题。 对于某些xml元素,我收到一个指数值,对于在类中表示它们,我使用了十进制值,当我反序列化xml文档时,它会失败

<fwdRate>-9.72316862724032E-05</fwdRate>
按要求

using System;
using System.IO;
using System.Xml.Serialization;

[XmlRoot(ElementName = "result")]
public class Result
{
    [XmlElement(ElementName = "fwdRate")]
    public decimal FwdRate { get; set; }
}       
public class Program
{
    public static void Main()
    {
         string val = "<result><fwdRate>-9.72316862724032E-05</fwdRate></result>";
         Result response = ParseXML(val);
  }
  static Result ParseXML(string value)
  {
      XmlSerializer serializer = new XmlSerializer(typeof(Result));
      using (TextReader reader = new StringReader(value))
      {
         return serializer.Deserialize(reader) as Result;
      }
  }

}
使用系统;
使用System.IO;
使用System.Xml.Serialization;
[XmlRoot(ElementName=“result”)]
公开课成绩
{
[xmlement(ElementName=“fwdRate”)]
公共十进制FwdRate{get;set;}
}       
公共课程
{
公共静态void Main()
{
字符串val=“-9.72316862724032E-05”;
结果响应=ParseXML(val);
}
静态结果解析XML(字符串值)
{
XmlSerializer serializer=新的XmlSerializer(typeof(Result));
使用(TextReader=new StringReader(值))
{
返回序列化程序。反序列化(读取器)作为结果;
}
}
}

正确的方法是通过实现IXmlSerializable接口来控制属性的反序列化方式:

在ReadXml方法中,您应该转换数字

var yourStringNumber = ...

this.fwdRate = Decimal.Parse(yourStringNumber, System.Globalization.NumberStyles.Float);
但这种方法需要您手动解析整个xml,这有时会有点开销

一个简单的解决方案(有味道但可能有用)就是向类中添加额外的fwdRateDecimal字段,并在序列化后实现该值

 private void ParseXML(string value)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(SwapDataSynapseResult));
        using (TextReader reader = new StringReader(value))
        {
            _result = serializer.Deserialize(reader) as SwapDataSynapseResult;
            _result.fwdRateDecimal = Decimal.Parse(_result.fwdRate, System.Globalization.NumberStyles.Float)
        }
    }
也可以直接在类型中实现转换:

[XmlRoot(ElementName = "result")]
public class Result
{
    [XmlElement(ElementName = "fwdRate")]
    public string FwdRateStr { get; set; }

    private string lastParsedValue = null;
    private decimal fwdRate = 0;

    [XmlIgnore]
    public decimal FwdRate 
    { 
     get 
     {
        if(FwdRateStr != lastParsedValue)
        {
             lastParsedValue = FwdRateStr
             fwdRate = Decimal.Parse(FwdRateStr ,System.Globalization.NumberStyles.Float)
        }

        return fwdRate
     }  
}
这就是解决方案:

using System;
using System.IO;
using System.Xml.Serialization;

[XmlRoot(ElementName = "result")]
public class Result
{
    [XmlElement(ElementName = "fwdRate")]
    public double FwdRate { get; set; }
}
public class Program
{
    public static void Main()
    {
        string val = "<result><fwdRate>-9.72316862724032E-05</fwdRate></result>";
        Result response = ParseXML(val);
        Console.WriteLine(response.FwdRate);
    }
    static Result ParseXML(string value)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(Result));
        using (TextReader reader = new StringReader(value))
        {
            return serializer.Deserialize(reader) as Result;
        }
    }

}
使用系统;
使用System.IO;
使用System.Xml.Serialization;
[XmlRoot(ElementName=“result”)]
公开课成绩
{
[xmlement(ElementName=“fwdRate”)]
公共双FwdRate{get;set;}
}
公共课程
{
公共静态void Main()
{
字符串val=“-9.72316862724032E-05”;
结果响应=ParseXML(val);
Console.WriteLine(response.FwdRate);
}
静态结果解析XML(字符串值)
{
XmlSerializer serializer=新的XmlSerializer(typeof(Result));
使用(TextReader=new StringReader(值))
{
返回序列化程序。反序列化(读取器)作为结果;
}
}
}
您不能修改传入的xml,但可以修改读取其数据的方式

将该数字读作
double
而不是
decimal
,您将获得正确的十进制精度

输出:

-972316862724032E-05


在XML中,十进制值不允许使用科学(指数)表示法()

要么:

  • 该值实际上是一个浮点值:在代码中放置一个
    浮点值
    /
    双精度值
    ,而不是
    十进制值
  • XML已损坏
同样,在C#中,默认情况下,不接受指数表示。 您可以通过实现一个新结构来覆盖此行为,该结构包装一个
decimal
,实现
IXmlSerializable
,并在反序列化时允许指数表示:

public struct XmlDecimal : IXmlSerializable
{
    public decimal Value { get; private set; }

    public XmlDecimal(decimal value) => Value = value;

    public XmlSchema GetSchema() => null;

    public void ReadXml(XmlReader reader)
    {
        var s = reader.ReadElementContentAsString();
        Value = decimal.TryParse(s, NumberStyles.Number | NumberStyles.AllowExponent,
            NumberFormatInfo.InvariantInfo, out var value)
            ? value
            : 0; // If parse fail the resulting value is 0. Maybe we can throw an exception here.
    }

    public void WriteXml(XmlWriter writer) => writer.WriteValue(Value);

    public static implicit operator decimal(XmlDecimal v) => v.Value;

    public override string ToString() => Value.ToString();
}
该缺陷是您必须在模型中的任何地方使用此结构,而不是
十进制


遗憾的是,您不能将此结构设置为只读,已解释过。

您能提供一个解决方案吗?张贴在、或else@aloisdgmovingtocodidact.com通过将其读取为
double
进行更新,可能会引入舍入错误。尝试
1.1e-1
。我们在这里是为了避免这种情况
decimal.TryParse
可以接受
numberstyle.AllowExponent
标志。谢谢。我想我将使用IXmlSerializable选择选项1。谢谢几个月前我也遇到了同样的问题,这是我带来的最好的解决方案。不过还是在看。
public struct XmlDecimal : IXmlSerializable
{
    public decimal Value { get; private set; }

    public XmlDecimal(decimal value) => Value = value;

    public XmlSchema GetSchema() => null;

    public void ReadXml(XmlReader reader)
    {
        var s = reader.ReadElementContentAsString();
        Value = decimal.TryParse(s, NumberStyles.Number | NumberStyles.AllowExponent,
            NumberFormatInfo.InvariantInfo, out var value)
            ? value
            : 0; // If parse fail the resulting value is 0. Maybe we can throw an exception here.
    }

    public void WriteXml(XmlWriter writer) => writer.WriteValue(Value);

    public static implicit operator decimal(XmlDecimal v) => v.Value;

    public override string ToString() => Value.ToString();
}