XMLシリアル化-null値を非表示にする


128

標準の.NET Xmlシリアライザーを使用している場合、すべてのnull値を非表示にする方法はありますか?以下は、私のクラスの出力の例です。nullに設定されている場合、null許容整数を出力したくありません。

現在のXML出力:

<?xml version="1.0" encoding="utf-8"?>
<myClass>
   <myNullableInt p2:nil="true" xmlns:p2="http://www.w3.org/2001/XMLSchema-instance" />
   <myOtherInt>-1</myOtherInt>
</myClass>

私が欲しいもの:

<?xml version="1.0" encoding="utf-8"?>
<myClass>
   <myOtherInt>-1</myOtherInt>
</myClass>

回答:


255

ShouldSerialize{PropertyName}メンバーをシリアル化する必要があるかどうかをXmlSerializerに通知するパターンを使用して関数を作成できます。

たとえば、クラスプロパティが呼び出されたMyNullableInt場合、

public bool ShouldSerializeMyNullableInt() 
{
  return MyNullableInt.HasValue;
}

ここに完全なサンプルがあります

public class Person
{
  public string Name {get;set;}
  public int? Age {get;set;}
  public bool ShouldSerializeAge()
  {
    return Age.HasValue;
  }
}

次のコードでシリアル化

Person thePerson = new Person(){Name="Chris"};
XmlSerializer xs = new XmlSerializer(typeof(Person));
StringWriter sw = new StringWriter();
xs.Serialize(sw, thePerson);

次のXMLの結果-年齢がないことに注意してください

<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Name>Chris</Name>
</Person>

9
一言:すごい!MSDNのShouldSerialize
2013

7
プロパティがXmlAttribute-attributeでマークされていない場合、ShouldSerializeパターンは機能します(属性はオプションである可能性があるため、これは機能するはずだと思いましたが、機能しません)。
Matze 2013

@Matze興味深い、私はそれを試していません。それもうまくいくと思いました。
クリステイラー

@ChrisTaylorはい。私は同じと思いました。トリッキーなことは、XmlSerializerインスタンスの作成が(型を反映する際のエラーが原因で)、null許容のintプロパティからXmlAttributeを削除するまで失敗したことです。
Matze 2013年

2
@PierredeLESPINAY-Visual Studio 2015以降では、以下を使用できます。public bool ShouldSerializeAge()=> Age.HasValue;
RooiWillie

34

Chris Taylorの記述に加えて、属性としてシリアル化されたものがある{PropertyName}Specified場合、シリアル化する必要があるかどうかを制御するために、クラスのプロパティに名前を付けることができます。コードで:

public class MyClass
{
    [XmlAttribute]
    public int MyValue;

    [XmlIgnore]
    public bool MyValueSpecified;
}

注意してください、{PropertyName}Specified属性はブール型でなければなりません。
sinsedrix

30

というプロパティが存在します XmlElementAttribute.IsNullable

IsNullableプロパティがtrueに設定されている場合、null参照に設定されているクラスメンバーに対してxsi:nil属性が生成されます。

次の例は、フィールドがXmlElementAttribute適用され、IsNullableプロパティがfalseに設定されているフィールドを示しています。

public class MyClass
{
   [XmlElement(IsNullable = false)]
   public string Group;
}

XmlElementAttributeシリアライゼーションなどで名前を変更するために他を見ることができます。


11
残念ながら、これは参照型に対してのみ機能し、値型またはNullable対応のものに対しては機能しません。
Vincent Sels 2013年

3
@VincentSelsは正しいです。MSDNによると、値の型にnullを含めることはできないため、値の型として型指定されたメンバーにIsNullableプロパティを適用することはできません。さらに、null許容値型の場合、このプロパティをfalseに設定することはできません。このようなタイプがnullの場合、xsi:nilをtrueに設定することでシリアル化されます。
bouvierr 2014年

12

一部のデフォルト値を定義すると、フィールドがシリアル化されなくなります。

    [XmlElement, DefaultValue("")]
    string data;

    [XmlArray, DefaultValue(null)]
    List<string> data;

残念ながら、これはnull許容値型では機能しません
bubi

2

自動生成されたタグのない自分のxmlを作成することを好みます。これでは、null値のノードの作成を無視できます。

public static string ConvertToXML<T>(T objectToConvert)
    {
        XmlDocument doc = new XmlDocument();
        XmlNode root = doc.CreateNode(XmlNodeType.Element, objectToConvert.GetType().Name, string.Empty);
        doc.AppendChild(root);
        XmlNode childNode;

        PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
        foreach (PropertyDescriptor prop in properties)
        {
            if (prop.GetValue(objectToConvert) != null)
            {
                childNode = doc.CreateNode(XmlNodeType.Element, prop.Name, string.Empty);
                childNode.InnerText = prop.GetValue(objectToConvert).ToString();
                root.AppendChild(childNode);
            }
        }            

        return doc.OuterXml;
    }

1
private static string ToXml(Person obj)
{
  XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
  namespaces.Add(string.Empty, string.Empty);

  string retval = null;
  if (obj != null)
  {
    StringBuilder sb = new StringBuilder();
    using (XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings() { OmitXmlDeclaration = true }))
    {
      new XmlSerializer(obj.GetType()).Serialize(writer, obj,namespaces);
    }
    retval = sb.ToString();
  }
  return retval;
}

1

私の場合、null許容変数/要素はすべてString型でした。したがって、私は単にチェックを実行し、NULLの場合はstring.Emptyを割り当てました。このようにして、不要なnilおよびxmlns属性を取り除きました(p3:nil = "true" xmlns:p3 = "http://www.w3.org/2001/XMLSchema-instance)

// Example:

myNullableStringElement = varCarryingValue ?? string.Empty

// OR

myNullableStringElement = myNullableStringElement ?? string.Empty

1
このソリューションは非常に限られており、文字列でのみ機能します。他のタイプの場合、空の文字列はまだ値です。一部のパーサーは属性を検索しようとし、見つかった場合は値をターゲットタイプに変換しようとします。そのようなパーサーの場合、欠落している属性はnullを意味し、属性がある場合は有効な値を持つ必要があります。
ZafarYousafi 2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.