LoginSignup
3
7

More than 3 years have passed since last update.

C#でXMLをシリアライズ出力するためのハックいろいろ

Posted at

指定された形式でXMLを出力しようとした時に毎回検索してはあっちこっちから情報拾ってる気がするのでまとめていく。
ちまちま増やしていくつもりです。

・環境
・C#7.0~8.0
・.Net Framework 4.7
・.Net Core 3.1

Nullable<T>=nullの項目のタグを出力しない

こんな場合。

モデル
    [XmlRoot]
    public class Library
    {
        [XmlElement]
        public User[] Users { get; set; }
    }

    public class User
    {
        [XmlElement]
        public int? Age { get; set; }

        [XmlElement]
        public string Name { get; set; }
    }
出力
<?xml version="1.0" encoding="utf-8"?>
<Library xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Users>
    <Age xsi:nil="true" /> <!--これを出力したくない-->
    <Name>user1</Name>
  </Users>
</Library>

bool型で制御したいプロパティ名+Specifiedのプロパティを定義することでタグの出力/非出力を制御できるのでそれを利用します。

コード
    [XmlRoot]
    public class Library
    {
        [XmlElement]
        public User[] Users { get; set; }
    }

    public class User
    {
        [XmlElement]
        public int? Age { get; set; }

        // Age == null の場合falseが返ってタグが出力されなくなる
        // 完全にシリアライズ制御用のプロパティなのでBrowsable=falseにしてインテリセンスで表示されないようにもしています
        [XmlIgnore, Browsable(false)]
        public bool AgeSpecified => Age.HasValue;

        [XmlElement]
        public string Name { get; set; }
    }
出力
<?xml version="1.0" encoding="utf-8"?>
<Library xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Users>
    <Name>user1</Name>
  </Users>
</Library>

構造体のシリアライズ

変換処理を書くだけといえばそれだけ

    [XmlRoot]
    public class Library
    {
        [XmlIgnore]
        public Color SomeColor { get; set; }

        [XmlElement("FontColor"), Browsable(false)]
        public string SomeColorValue
        {
            get { return $"#{SomeColor.A}{SomeColor.R}{SomeColor.G}{SomeColor.B}"; }
            set { SomeColor = ColorTranslator.FromHtml(value); }
        }
    }
出力
<?xml version="1.0" encoding="utf-8"?>
<Library xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <FontColor>#12345678</FontColor>
</Library>

DateTimeのフォーマットなんかもこれでやらざるをえない気がする。

xmlnsを外す

ちょっと古いアプリとの連携とかで要求されがちな気がする。
xmlをプレーンテキストとして処理する場合とかにも

コード
    class Program
    {
        static void Main(string[] args)
        {
            var app = new Library() { Names = new string[] { } }

            using (var writer = new StreamWriter("application.xml"))
            {
                // 空白のnamespaceを用意する
                var ns = new XmlSerializerNamespaces();
                ns.Add(string.Empty, string.Empty);

                var serializer = new XmlSerializer(typeof(Library));
                serializer.Serialize(writer, app, ns); // 空白のnamespaceを使ってシリアライズ
            }
        }
    }

    [XmlRoot]
    public class Library
    {
        public string[] Names { get; set; }
    }
出力
<?xml version="1.0" encoding="utf-8"?>
<Library>
  <Names />
</Library>

後書き

なんかもっといい方法あったら教えてほしいなって。

3
7
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
3
7