Xml 직렬화-null 값 숨기기


128

표준 .NET Xml Serializer를 사용할 때 모든 null 값을 숨길 수있는 방법이 있습니까? 아래는 내 수업의 출력 예입니다. nullable 정수가 null로 설정되어 있으면 nullable 정수를 출력하고 싶지 않습니다.

현재 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);

followng 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

7
ShouldSerialize 패턴은 속성에 XmlAttribute 속성으로 표시되지 않은 경우에만 작동합니다 (속성이 선택적 일 수는 있지만 작동하지 않을 것이라고 생각했습니다).
Matze

@ Matze 흥미로운, 나는 그것을 시도하지 않았습니다. 또한 작동한다고 가정했을 것입니다.
Chris Taylor

@ChrisTaylor 예; 나는 똑같이 가정했다. 까다로운 점은 XmlSerializer 인스턴스 생성이 nullable int-property에서 XmlAttribute를 제거 할 때까지 (유형을 반영 할 때 오류로 인해) 실패했습니다.
Matze

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속성은 bool 형식이어야합니다.
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

3
@VincentSels가 정확합니다. MSDN의 말 : 값 형식은 null을 포함 할 수 없으므로 IsNullable 속성을 값 형식으로 입력 된 멤버에 적용 할 수 없습니다. 또한 널 입력 가능 값 유형의 경우이 특성을 false로 설정할 수 없습니다. 이러한 유형이 널이면 xsi : nil을 true로 설정하여 직렬화됩니다.
bouvierr

12

일부 기본값을 정의하면 필드가 직렬화되지 않습니다.

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

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

불행히도, 이것은 nullable 값 유형에는 적용되지 않습니다
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

필자의 경우 nullable 변수 / 요소는 모두 String 유형이었습니다. 그래서 단순히 검사를 수행하고 문자열을 할당했습니다 .NULL의 경우 비어 있습니다. 이렇게하면 불필요한 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
이 솔루션은 매우 제한적이며 문자열에서만 작동합니다. 다른 유형의 경우 빈 문자열은 여전히 ​​값입니다. 일부 파서는 속성을 찾으려고 시도하면 값을 대상 유형으로 변환하려고 시도합니다. 이러한 구문 분석기에서 누락 된 속성은 널을 의미하며 속성이있는 경우 올바른 값을 가져야합니다.
ZafarYousafi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.