XML序列化-隐藏空值


128

使用标准的.NET Xml序列化器时,有什么方法可以隐藏所有空值?下面是我的类输出的示例。我不想输出可为空的整数,如果它们设置为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>

Answers:


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应该序列化
scheien

7
如果属性未用XmlAttribute-attribute标记,则ShouldSerialize模式仅起作用(我认为这应该起作用,因为属性可以是可选的,但不是可选的)。
Matze 2013年

@Matze有趣,我没有尝试过。我也会以为它会工作。
克里斯·泰勒

@ChrisTaylor是的;我假设相同。棘手的事情是XmlSerializer实例的创建失败(由于反映类型时出错),直到我从可为空的int属性中删除了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 2012年

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说:您不能将IsNullable属性应用于键入为值类型的成员,因为值类型不能包含null。此外,对于可为空的值类型,您不能将此属性设置为false。当此类类型为null时,将通过将xsi:nil设置为true来对其进行序列化。
bouvierr 2014年

12

您可以定义一些默认值,这样可以防止字段被序列化。

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

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

不幸的是,这不适用于可空值类型
bubi

2

我更喜欢创建没有自动生成标签的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;
    }

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

在我的情况下,可为空的变量/元素都是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
该解决方案非常有限,仅适用于字符串。对于其他类型,空字符串仍然是一个值。一些解析器尝试查找属性,如果找到,则尝试将值转换为目标类型。对于此类解析器,缺少属性意味着为null,如果存在属性,则它必须具有有效值。
ZafarYousafi 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.