XML-сериализация - скрыть нулевые значения - PullRequest
109 голосов
/ 28 апреля 2011

При использовании стандартного сериализатора .NET Xml можно ли как-нибудь скрыть все нулевые значения? Ниже приведен пример вывода моего класса. Я не хочу выводить обнуляемые целые числа, если они установлены в нуль.

Текущий вывод 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>

Ответы [ 7 ]

226 голосов
/ 28 апреля 2011

Вы можете создать функцию с шаблоном 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>
31 голосов
/ 28 апреля 2011

В дополнение к тому, что написал Крис Тейлор: если у вас есть что-то, сериализованное в качестве атрибута, вы можете иметь свойство в своем классе с именем {PropertyName}Specified, чтобы контролировать, должно ли оно быть сериализовано.В коде:

public class MyClass
{
    [XmlAttribute]
    public int MyValue;

    [XmlIgnore]
    public bool MyValueSpecified;
}
22 голосов
/ 28 апреля 2011

Существует свойство с именем XmlElementAttribute.IsNullable

Если для свойства IsNullable установлено значение true, атрибут xsi: nil создается для членов класса, для которых установлена ​​нулевая ссылка.

В следующем примере показано поле с примененным к нему XmlElementAttribute и свойством IsNullable, установленным на false.

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

Вы можете посмотреть другие XmlElementAttribute для измененияимена в сериализации и т. д.

10 голосов
/ 15 декабря 2013

Вы можете определить некоторые значения по умолчанию, и это предотвратит сериализацию полей.

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

    [XmlArray, DefaultValue(null)]
    List<string> data;
1 голос
/ 07 мая 2014

В моем случае все переменные / элементы, допускающие значение nullable, имели тип String.Итак, я просто выполнил проверку и присвоил им string.Empty в случае 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 голос
/ 18 октября 2012
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;
}
0 голосов
/ 10 июня 2016

Я предпочитаю создавать свой собственный xml без автоматически сгенерированных тегов.В этом я могу игнорировать создание узлов с нулевыми значениями:

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;
    }
...