Сериализация Xml - Скрыть нулевые значения
При использовании стандартного сериализатора .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>
Ответы
Ответ 1
Вы можете создать функцию с шаблоном 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-формате followng. Обратите внимание, что нет Age
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Chris</Name>
</Person>
Ответ 2
В дополнение к тому, что написал Крис Тейлор: если у вас есть что-то сериализованное как атрибут, вы можете иметь свойство в своем классе с именем {PropertyName}Specified
для управления, если оно должно быть сериализовано. В коде:
public class MyClass
{
[XmlAttribute]
public int MyValue;
[XmlIgnore]
public bool MyValueSpecified;
}
Ответ 3
Существует свойство, называемое XmlElementAttribute.IsNullable
Если для свойства IsNullable установлено значение true, атрибут xsi: nil создается для членов класса, для которых задана нулевая ссылка.
В следующем примере показано поле с приложенным к нему символом XmlElementAttribute
, а свойство IsNullable - false.
public class MyClass
{
[XmlElement(IsNullable = false)]
public string Group;
}
Вы можете посмотреть на другой XmlElementAttribute
для изменения имен в сериализации и т.д.
Ответ 4
Вы можете определить некоторые значения по умолчанию, и это предотвращает сериализацию полей.
[XmlElement, DefaultValue("")]
string data;
[XmlArray, DefaultValue(null)]
List<string> data;
Ответ 5
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;
}
Ответ 6
В моем случае переменными/элементами с нулевым значением были все типы 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
Ответ 7
Я предпочитаю создавать свой собственный 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;
}