指定された形式でXMLを出力しようとした時に毎回検索してはあっちこっちから情報拾ってる気がするのでまとめていく。
ちまちま増やしていくつもりです。
・環境
・C#7.0~8.0
・.Net Framework 4.7
・.Net Core 3.1
Nullable<T>=null
の項目のタグを出力しない
こんな場合。
モデル
[XmlRoot]publicclassLibrary{[XmlElement]publicUser[]Users{get;set;}}publicclassUser{[XmlElement]publicint?Age{get;set;}[XmlElement]publicstringName{get;set;}}
出力
<?xml version="1.0" encoding="utf-8"?><Libraryxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Users><Agexsi:nil="true"/><!--これを出力したくない--><Name>user1</Name></Users></Library>
bool型で制御したいプロパティ名+Specifiedのプロパティを定義することでタグの出力/非出力を制御できるのでそれを利用します。
コード
[XmlRoot]publicclassLibrary{[XmlElement]publicUser[]Users{get;set;}}publicclassUser{[XmlElement]publicint?Age{get;set;}// Age == null の場合falseが返ってタグが出力されなくなる// 完全にシリアライズ制御用のプロパティなのでBrowsable=falseにしてインテリセンスで表示されないようにもしています[XmlIgnore,Browsable(false)]publicboolAgeSpecified=>Age.HasValue;[XmlElement]publicstringName{get;set;}}
出力
<?xml version="1.0" encoding="utf-8"?><Libraryxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Users><Name>user1</Name></Users></Library>
構造体のシリアライズ
変換処理を書くだけといえばそれだけ
[XmlRoot]publicclassLibrary{[XmlIgnore]publicColorSomeColor{get;set;}[XmlElement("FontColor"),Browsable(false)]publicstringSomeColorValue{get{return$"#{SomeColor.A}{SomeColor.R}{SomeColor.G}{SomeColor.B}";}set{SomeColor=ColorTranslator.FromHtml(value);}}}
出力
<?xml version="1.0" encoding="utf-8"?><Libraryxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema"><FontColor>#12345678</FontColor></Library>
DateTimeのフォーマットなんかもこれでやらざるをえない気がする。
xmlnsを外す
ちょっと古いアプリとの連携とかで要求されがちな気がする。
xmlをプレーンテキストとして処理する場合とかにも
コード
classProgram{staticvoidMain(string[]args){varapp=newLibrary(){Names=newstring[]{}}using(varwriter=newStreamWriter("application.xml")){// 空白のnamespaceを用意するvarns=newXmlSerializerNamespaces();ns.Add(string.Empty,string.Empty);varserializer=newXmlSerializer(typeof(Library));serializer.Serialize(writer,app,ns);// 空白のnamespaceを使ってシリアライズ}}}[XmlRoot]publicclassLibrary{publicstring[]Names{get;set;}}
出力
<?xml version="1.0" encoding="utf-8"?><Library><Names/></Library>
後書き
なんかもっといい方法あったら教えてほしいなって。