【发布时间】:2016-09-14 06:51:37
【问题描述】:
这个问题在 SO 上被问了很多次,但没有一个解决方案对我有帮助。
使用 dataContractSerializer 将我的数据结构序列化为 XML 文件。 (反)序列化代码如下:
public static void serialize<T>(T xObject, string xFilePath, string xIndent = "")
{
XmlWriterSettings xSettings = ( xIndent == "" ? new XmlWriterSettings {Indent = false } : new XmlWriterSettings { Indent = true, IndentChars = xIndent } );
using (XmlWriter xStream = XmlWriter.Create(xFilePath, xSettings))
new DataContractSerializer(typeof(T)).WriteObject(xStream, xObject);
}
public static T deserialize<T>(string xFilePath)
{
using (FileStream xStream = new FileStream(xFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
DataContractSerializer xSerializer = new DataContractSerializer(typeof(T));
return (T)xSerializer.ReadObject(xStream);
}
}
写出的XML的一个sn-p是
<?xml version="1.0" encoding="utf-8"?>
<PxePriceListEod xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="libTypes.salesApp">
<DateOfValidity xmlns:d2p1="libTypes">
<d2p1:_x002E_>2016-09-09T00:00:00</d2p1:_x002E_>
</DateOfValidity>
<PriceRecords>
<AbstractPxePriceRecordEod i:type="PxePriceRecordEodBal">
<Product xmlns:d4p1="libTypes">
<d4p1:Ccy>
<d4p1:_x002E_>EUR</d4p1:_x002E_>
</d4p1:Ccy>
<d4p1:Commodity>
<d4p1:_x002E_>Electricity</d4p1:_x002E_>
</d4p1:Commodity>
<d4p1:Duration>
<d4p1:_x002E_>Month</d4p1:_x002E_>
</d4p1:Duration>
<d4p1:Exchange>
<d4p1:_x002E_>Pxe</d4p1:_x002E_>
</d4p1:Exchange>
<d4p1:Period>
<d4p1:_x002E_>9</d4p1:_x002E_>
</d4p1:Period>
<d4p1:Type>
<d4p1:_x002E_>Base</d4p1:_x002E_>
</d4p1:Type>
<d4p1:Year>
<d4p1:_x002E_>2016</d4p1:_x002E_>
</d4p1:Year>
</Product>
<IsDeduced xmlns:d4p1="libTypes">
<d4p1:_x002E_>false</d4p1:_x002E_>
</IsDeduced>
<IsInterpolated xmlns:d4p1="libTypes">
<d4p1:_x002E_>false</d4p1:_x002E_>
</IsInterpolated>
<IsSynthetic xmlns:d4p1="libTypes">
<d4p1:_x002E_>false</d4p1:_x002E_>
</IsSynthetic>
<Price xmlns:d4p1="libTypes">
<d4p1:_x002E_>30.45</d4p1:_x002E_>
</Price>
<DateOfValidity xmlns:d4p1="libTypes">
<d4p1:_x002E_>2016-09-09T00:00:00</d4p1:_x002E_>
</DateOfValidity>
</AbstractPxePriceRecordEod>
... more AbstractPxePriceRecordEod elements ...
</PriceRecords>
</PxePriceListEod>
问题的特点:
- 错误指向 Line=0, Position=1(没有意义)
- 没有名称包含“.”的元素
- 进入文件的所有类都用
DataContract正确修饰 - 检查 XML 文件是否真正采用 UTF-8 编码(由 Notepad++ 读取时),并且 SO 上列出的(反)序列化代码的其他版本(隐式指定 UTF-8 编码)均无帮助
- 我知道文件很难看(自动生成的元素名称,如“d4p1:x002E” - 我是这家公司唯一的开发人员,不幸的是我没有时间很好地装饰 100 多个课程)
- 2.5 年来一切正常,问题从今天开始。
非常感谢任何提示, 丹尼尔
更新
我添加了最少量的代码来重现问题here。 application 尝试从 xml 文件中读取给定的类,具有问题 dataContractNames 的类位于 library\+support\+qprimitive。
【问题讨论】:
-
您的 XML 无效。 第 2 行的 XML 解析错误:xmlns: URI libTypes.salesApp 不是绝对的 验证给定示例后
-
_x002E_是XmlConvert.EncodeLocalName()对字符串"."进行编码的方式。所以你的<d2p1:_x002E_>和<d4p1:_x002E_>元素都有本地名称,在解码时映射到"."。见dotnetfiddle.net/phUYO3。您能否分享与DateOfValidity对应的类型,以便我们查看 XML 是如何生成的?是实现IXmlSerializable还是ISerializable? -
更好的是,你能分享一个minimal reproducible example 来序列化产生
<d2p1:_x002E_>元素的类型吗? -
@dbc:谢谢,就是这样。我的一个课程使用
[DataMember(Name = ".")]- 我在写这篇文章时是 XML 新手,我想“让我们让 XML 更小”。有趣的是,运行时多年来都没有抱怨过这个问题。现在......有很多使用这种格式编写的文件,我可以对代码进行的最小更改是什么,使我可以读取这些文件?使用此 DataMemberName 的类只有一个成员并且是密封的。我尝试使用 [DataMember(Order = 0)] 而不是 DataMemberName,但没有帮助。非常感谢! -
@DanielBencik - 我尝试用
[DataMember(Name = ".")]制作一个示例类,并且能够成功反序列化它。为了帮助更多,能否分享一下上面反序列化XML失败的类?或者您能否通过源代码控制确定过去几天发生的变化?如果没有minimal reproducible example,我会花时间猜测你的类定义是什么,并尝试看看我是否可以重现这个问题,这不太可能很快成功。
标签: c# xml datacontractserializer