4
6

More than 5 years have passed since last update.

XmlをSerializeする際、intやenumで定義した属性または要素を省略可能にする

Posted at

オブジェクトをXMLにシリアライズする際、enumやintで定義されたプロパティのタグ(もしくは属性)を省略して表示することが難しいです。

App.xaml.cs
    class Program
    {
        static void Main(string[] args)
        {
            DataClass dataClass = new DataClass()
            {
                IntParam = 2,
                DataEnumParam = DataEnum.Two,
            };
            XmlSerializer xmlserializer = new XmlSerializer(typeof(DataClass));
            StringWriter sw = new StringWriter();
            xmlserializer.Serialize(sw, dataClass);
            Console.WriteLine(sw.ToString());
            Console.ReadLine();
        }
    }

    [XmlRoot]
    public class DataClass
    {
        /// <summary>
        /// この属性を非表示にしたい
        /// </summary>
        [XmlElement]
        public int IntParam { get; set; }

        /// <summary>
        /// この要素を非表示にしたい
        /// </summary>
        [XmlAttribute]
        public DataEnum DataEnumParam { get; set; }
    }
    public enum DataEnum
    {
        One,
        Two,
        Three,
    }

コンソールに表示されるXml

<?xml version="1.0" encoding="utf-16"?>
<DataClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" DataEnumParam="Two">
<IntParam>2</IntParam>
</DataClass>

stringのような元々nullを許容している型なら、nullを指定すればタグを省略できますが、null許容型でない型については、nullable(例:int?やNullable)にしてシリアライズするとエラーとなってしまうなど、扱いが難しいです。

そこで項目名+"Specified"というboolの項目をXmlIgnore属性付きで定義しておき、項目にfalseを設定することで省略が可能となります。

App.xaml.cs
    class Program
    {
        static void Main(string[] args)
        {
            DataClass dataClass = new DataClass()
            {
                IntParam = 2,
                //省略するようfalseを指定(初期値もfalseですが、一応)
                IntParamSpecified = false,
                DataEnumParam = DataEnum.Two,
                //省略するようfalseを指定(初期値もfalseですが、一応)
                DataEnumParamSpecified = false,
            };
            XmlSerializer xmlserializer = new XmlSerializer(typeof(DataClass));
            StringWriter sw = new StringWriter();
            xmlserializer.Serialize(sw, dataClass);
            Console.WriteLine(sw.ToString());
            Console.ReadLine();
        }
    }

    [XmlRoot]
    public class DataClass
    {
        /// <summary>
        /// この属性を非表示にしたい
        /// </summary>
        [XmlElement]
        public int IntParam { get; set; }

        /// <summary>
        /// IntParamの省略専用プロパティ
        /// </summary>
        [XmlIgnore]
        public bool IntParamSpecified { get; set; }

        /// <summary>
        /// この要素を非表示にしたい
        /// </summary>
        [XmlAttribute]
        public DataEnum DataEnumParam { get; set; }

        /// <summary>
        /// DataEnumParamの省略専用プロパティ
        /// </summary>
        [XmlIgnore]
        public bool DataEnumParamSpecified { get; set; }
    }
    public enum DataEnum
    {
        One,
        Two,
        Three,
    }

コンソールに表示されるXml

<?xml version="1.0" encoding="utf-16"?>
<DataClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />

XmlIgnore属性を外したり、SPECIFIEDのようにSpecifiedの大文字小文字を変更すると消えないようです。

Xsd.exeが生成したintやenumに~Specifiedプロパティがよく生成されたりします。
よくDom使っていたころは、省略可能項目はstringでデータを扱うことで何とかやりくりしていたのですが、これならintやenumのままでも省略可能です。

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6