Status Code 303 - See Other

サーバサイド、iOS・アンドロイドアプリ、インフラレベルの話まで幅広くやってます。情報の誤りや指摘・意見などは自由にどうぞ。

C#のドキュメントコメント要素をトリムする方法

概要

XML処理のめんどくさい問題にぶち当たったのでメモ。
ドキュメントコメントからXML解析しているときに各要素の最初・最後の空白文字がうまくトリムできなかった。
今回書くのは、その解決方法。

問題事象

まず、以下のように書いたらなんか表示がおかしい。

    // XMLのマッピングオブジェクト
    [XmlRoot(ElementName="member")]
    public class Class
    {
        [XmlElement(ElementName = "summary")]
        public string Summary { get; set; }

        [XmlElement(ElementName = "typeparam")]
        public List<TypeParam> TypeParams { get; set; }

    }
    
     // TはXMLの読み込み結果をどんな形式で返すかを決定する型
     public static T Parse<T>(string documentcomment)
     {
         using (Stream stream = new MemoryStream(Encoding.Unicode.GetBytes(documentcomment.Trim())))
         {
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            return (T)serializer.Deserialize(stream);
         }
     }

     // 使い方
     public static void Main(string[] args)
     {
          Class klass = XMLParser.Parse<Class>(@"
 <member>
 <summary>
 抽象クラス.
 </summary>
 <typeparam name=""T"">格納オブジェクト型</typeparam>
 </member>");

           Console.WriteLine("サマリ:" + klass.Summary);
           Console.WriteLine("型パラメータ:" + klass.TypeParams[0].Name + " (" + klass.TypeParams[0].Value + ")");
      }

すると、サマリは以下のような感じに改行や空白が入る。

サマリ:
 抽象クラス.

型パラメータ:T (格納オブジェクト型)

原因・解決法

これは、 <summary>~</summary>の間に抽象クラス.の前後に空白文字があり、XmlSerializerはそれを保持するから。
代わりに型パラメータの方は、空白が入っていないため想定通りに出ている

各要素でトリムをしたいのだ。なんとかならんのか。が、XmlSerializer にはそれっぽいメソッドはない感じ。
マッピングオブジェクト作成後に各要素をトリムするという恐ろしくスマートでないやり方も・・・。

が、調べてるといいものが見つかった。
.net - XML Deserialization of string elements with newlines in C# - Stack Overflow

You can create custom XmlTextReader class:

public class CustomXmlTextReader : XmlTextReader
{
public CustomXmlTextReader(Stream stream) : base(stream) { }

public override string ReadString()
{
return base.ReadString().Trim();
}
}

いけた!

        private class CustomXmlTextReader : XmlTextReader
        {
            public CustomXmlTextReader(Stream stream) : base(stream) { }

            public override string ReadString()
            {
                return base.ReadString().Trim();
            }
        }

        public static T Parse<T>(string documentcomment)
        {

            using (Stream stream = new MemoryStream(Encoding.Unicode.GetBytes(documentcomment.Trim())))
            {
                var reader = new CustomXmlTextReader(stream);

                XmlSerializer serializer = new XmlSerializer(typeof(T));
                return (T)serializer.Deserialize(reader);
            }
        }
サマリ:抽象クラス.
型パラメータ:T (格納オブジェクト型)