C# 解析Xml文档中的指数值
反序列化对象(我无法修改)时出现问题。 对于某些xml元素,我收到一个指数值,对于在类中表示它们,我使用了十进制值,当我反序列化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
<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已损坏
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();
}