简体   繁体   English

为反序列化XML时为null的属性设置默认值

[英]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. 注意,在我的类的DataAlignment属性中,我设置了默认值(如果不存在)。 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.

相关问题 如果在反序列化期间字符串为null,则设置默认值 - Put a default value if the string is null during deserializing 反序列化 XML 文件属性 - Deserializing XML File attributes 反序列化xml属性 - Deserializing xml attributes 在C#(.NET 3.5)中反序列化xml时是否可以设置默认值? - Is it possible to set a default value when deserializing xml in C# (.NET 3.5)? 使用自定义 ContractResolver,在将 null JSON 属性反序列化为值类型成员时如何设置默认值而不是 null? - Using a custom ContractResolver, how to set a default value instead of null when deserializing a null JSON property to a value-type member? System.Text.Json:反序列化时,如何忽略在构造函数中设置了默认值的属性的 null 或空字符串值? - System.Text.Json: when deserializing, how can I ignore a null or empty string value for a property that has a default value set in the constructor? 基于元素属性反序列化XML - Deserializing XML Based on Element Attributes XML反序列化C#时设置默认值 - Set default value while XML Deserialization C# 使用多个元素属性反序列化XML文件 - 属性不反序列化 - Deserializing XML File with multiple element attributes - attributes are not deserializing 如何在反序列化时字段为空时将默认值设置为Guid - how to set default value as Guid when field is blank at the time of deserializing
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM