[英]Set default value for attributes which are null while deserializing XML
I have a xml file which I am trying to deserialize. 我有一个要反序列化的xml文件。 I am implementing IXmlSerializable interface for Serialization and Deserialization.
我正在实现用于序列化和反序列化的IXmlSerializable接口。 I don't see any problem with the Serialization.
我看不到序列化有任何问题。 But with the deserialization I have few problems.
但是通过反序列化,我几乎没有问题。 1).
1)。 I am using xml reader's 'ReadToFollowing' for reading elements.
我正在使用xml阅读器的“ ReadToFollowing”来读取元素。 With this approach I have to read the values in the order of elements.
使用这种方法,我必须按元素顺序读取值。 If there is any mismatch in the order I am not able to read the remainig values.
如果顺序不匹配,我将无法读取restig值。 2).
2)。 As per my requirement I have to provide backward compatibility in deserializing the xml.
根据我的要求,我必须在反序列化xml中提供向后兼容性。 Because of this when I load some of the old version xml files(which may not contain all the elements as the latest version xml), 'ReadToFollowing' throwing exceptions.
因此,当我加载一些旧版本的xml文件(可能不包含所有元素作为最新版本的xml)时,“ ReadToFollowing”引发异常。
Latest version Xml 最新版本Xml
<LEFTSECTION>
<DATA />
<FONTNAME>Arial</FONTNAME>
<FONTSTYLE>Regular</FONTSTYLE>
<FONTSIZE>10</FONTSIZE>
<TEXTCOLOR>-16777216</TEXTCOLOR>
<STRIKEOUT>0</STRIKEOUT>
<UNDERLINE>0</UNDERLINE>
<BORDER>0</BORDER>
<IMAGE>0</IMAGE>
<IMAGENAME />
<ALIGNMENT>4</ALIGNMENT>
<SECTIONHEIGHT>0.5454546</SECTIONHEIGHT>
<SECTIONWIDTH>0.33</SECTIONWIDTH>
</LEFTSECTION>
Old version Xml 旧版本Xml
<LEFTSECTION>
<DATA>asas#APP_OEM_NAME#</DATA>
<FONTNAME>Arial Unicode MS</FONTNAME>
<FONTSTYLE>Regular</FONTSTYLE>
<FONTSIZE>10</FONTSIZE>
<TEXTCOLOR>-16777216</TEXTCOLOR>
<STRIKEOUT>0</STRIKEOUT>
<UNDERLINE>0</UNDERLINE>
<BORDER>0</BORDER>
<IMAGE>0</IMAGE>
<IMAGENAME>
</IMAGENAME>
</LEFTSECTION>
Please help me on this. 请帮我。
Okay. 好的。 I've had a play and this is what I've come up with:
我玩过,这是我想出的:
Serializeable class: 可序列化的类:
[Serializable]
[XmlRoot("LEFTSECTION")]
public class NewClass
{
[XmlElement("DATA")]
[System.ComponentModel.DefaultValueAttribute("")]
public string Data;
[XmlElement("FONTNAME")]
public string FontName;
[XmlElement("FONTSTYLE")]
public string FontStyle;
[XmlElement("FONTSIZE")]
public int FontSize;
[XmlElement("TEXTCOLOR")]
public int TextColor;
[XmlElement("STRIKEOUT")]
public int Strikeout;
[XmlElement("UNDERLINE")]
public int Underline;
[XmlElement("BORDER")]
public int Border;
[XmlElement("IMAGE")]
public int Image;
[XmlElement("IMAGENAME")]
public string ImageName;
[System.ComponentModel.DefaultValue(0)]
[XmlElement("ALIGNMENT")]
public int Alignment;
[XmlElement("SECTIONHEIGHT")]
public double SectionHeight;
[XmlElement("SECTIONWIDTH")]
public double SectionWidth;
}
Then code in my test program: 然后在我的测试程序中编写代码:
NewClass test = new NewClass();
XmlSerializer serializer = new XmlSerializer(typeof(NewClass));
FileStream file = new FileStream("input.xml", FileMode.Open);
test = (NewClass) serializer.Deserialize(file);
file.Close();
file = new FileStream("old.xml", FileMode.Open);
test = (NewClass)serializer.Deserialize(file);
file.Close();
Contents of input.xml: input.xml的内容:
<?xml version="1.0" encoding="utf-8" ?>
<LEFTSECTION>
<DATA />
<FONTNAME>Arial</FONTNAME>
<FONTSTYLE>Regular</FONTSTYLE>
<FONTSIZE>10</FONTSIZE>
<TEXTCOLOR>-16777216</TEXTCOLOR>
<STRIKEOUT>0</STRIKEOUT>
<UNDERLINE>0</UNDERLINE>
<BORDER>0</BORDER>
<IMAGE>0</IMAGE>
<IMAGENAME />
<ALIGNMENT>4</ALIGNMENT>
<SECTIONHEIGHT>0.5454546</SECTIONHEIGHT>
<SECTIONWIDTH>0.33</SECTIONWIDTH>
</LEFTSECTION>
Contents of old.xml: old.xml的内容:
<LEFTSECTION>
<DATA>asas#APP_OEM_NAME#</DATA>
<FONTNAME>Arial Unicode MS</FONTNAME>
<FONTSTYLE>Regular</FONTSTYLE>
<FONTSIZE>10</FONTSIZE>
<TEXTCOLOR>-16777216</TEXTCOLOR>
<STRIKEOUT>0</STRIKEOUT>
<UNDERLINE>0</UNDERLINE>
<BORDER>0</BORDER>
<IMAGE>0</IMAGE>
<IMAGENAME>
</IMAGENAME>
</LEFTSECTION>
This populates my class correctly. 这样可以正确填充我的班级。 Notice that on
Data
and Alignment
properties of my class I set default values if they don't exist. 注意,在我的类的
Data
和Alignment
属性中,我设置了默认值(如果不存在)。 Also they're all renamed from what is in the file. 同样,它们都从文件中的内容重命名。
I hope that this helps. 我希望这个对你有用。
edit 编辑
Ah I see, you're stuck with IXmlSerializable methods for your classes. 啊,我明白了,您对类的使用IXmlSerializable方法感到困惑。
Try this it's not pretty but it appears to work: 试试看这不是很漂亮,但它似乎可以工作:
Here's my IXMLSerializable class: 这是我的IXMLSerializable类:
public class XmlSerializableNewClass : IXmlSerializable
{
public string Data;
public string FontName;
public string FontStyle;
public int FontSize;
public int TextColor;
public int Strikeout;
public int Underline;
public int Border;
public int Image;
public string ImageName;
public int Alignment;
public double SectionHeight;
public double SectionWidth;
public string[]elementNames={"DATA", "FONTNAME", "FONTSTYLE","FONTSIZE","TEXTCOLOR","STRIKEOUT", "UNDERLINE", "BORDER", "IMAGE", "IMAGENAME", "ALIGNMENT", "SECTIONHEIGHT", "SECTIONWIDTH"};
#region IXmlSerializable Members
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
//set default values
Data=string.Empty;
FontName = string.Empty;
FontStyle = string.Empty;
FontSize = 0;
TextColor = 0;
Strikeout = 0;
Underline = 0;
Border = 0;
Image = 0;
ImageName = string.Empty;
Alignment = 0;
SectionHeight = 0.0;
SectionWidth = 0.0;
reader.MoveToContent();
Boolean isEmptyElement= false;
isEmptyElement = reader.IsEmptyElement;
reader.ReadStartElement();
for (int i=0; i< elementNames.Length; i++)
{
isEmptyElement = reader.IsEmptyElement;
string s = reader.Name;
switch (s)
{
case "DATA":
if (!isEmptyElement)
{
Data = reader.ReadElementString("DATA");
}
else
{
Data = string.Empty;
reader.ReadStartElement();
}
break;
case "FONTNAME":
if (!isEmptyElement)
{
FontName = reader.ReadElementString("FONTNAME");
}
else
{
FontName = string.Empty;
reader.ReadStartElement();
}
break;
case "FONTSTYLE":
if (!isEmptyElement)
{
FontStyle = reader.ReadElementString("FONTSTYLE");
}
else
{
FontStyle = string.Empty;
reader.ReadStartElement();
}
break;
case "FONTSIZE":
if (!isEmptyElement)
{
FontSize = reader.ReadElementContentAsInt();
}
else
{
FontSize = 0;
reader.ReadEndElement();
}
break;
case "TEXTCOLOR":
if (!isEmptyElement)
{
TextColor = reader.ReadElementContentAsInt();
}
else
{
TextColor = 0;
reader.ReadStartElement();
}
break;
case "STRIKEOUT":
if (!isEmptyElement)
{
Strikeout = reader.ReadElementContentAsInt();
}
else
{
Strikeout = 0;
reader.ReadStartElement();
}
break;
case "UNDERLINE":
if (!isEmptyElement)
{
Underline = reader.ReadElementContentAsInt();
}
else
{
Underline = 0;
reader.ReadStartElement();
}
break;
case "BORDER":
if (!isEmptyElement)
{
Border = reader.ReadElementContentAsInt();
}
else
{
Border = 0;
reader.ReadStartElement();
}
break;
case "IMAGE":
if (!isEmptyElement)
{
Image = reader.ReadElementContentAsInt();
}
else
{
Image = 0;
reader.ReadStartElement();
}
break;
case "IMAGENAME":
if (!isEmptyElement)
{
ImageName = reader.ReadElementString("IMAGENAME");
}
else
{
ImageName = string.Empty;
reader.ReadStartElement();
}
break;
case "ALIGNMENT":
if (!isEmptyElement)
{
Alignment = reader.ReadElementContentAsInt();
}
else
{
Alignment = 0;
reader.ReadStartElement();
}
break;
case "SECTIONHEIGHT":
if (!isEmptyElement)
{
SectionHeight = reader.ReadElementContentAsDouble();
}
else
{
SectionHeight = 0;
reader.ReadStartElement();
}
break;
case "SECTIONWIDTH":
if (!isEmptyElement)
{
SectionWidth = reader.ReadElementContentAsDouble();
}
else
{
SectionWidth = 0;
reader.ReadEndElement();
}
break;
}
}
reader.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
throw new NotImplementedException();
}
#endregion
}
I've gone a bit overboard with handling empty elements. 我在处理空元素方面有些落伍。
Here's the calling code, everything else is the same: 这是调用代码,其他所有内容都相同:
XmlSerializableNewClass test2 = new XmlSerializableNewClass();
System.Xml.XmlReaderSettings settings = new System.Xml.XmlReaderSettings();
settings.ConformanceLevel = System.Xml.ConformanceLevel.Fragment;
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
System.Xml.XmlReader reader = System.Xml.XmlReader.Create("input.xml", settings);
test2.ReadXml(reader);
reader = System.Xml.XmlReader.Create("old.xml", settings);
test2.ReadXml(reader);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.