Remove xml element with xsi:nil=“true” C# serialization

若如初见. 提交于 2021-02-09 10:56:53

问题


I have an XML which has some values and at times there can be null values as shown below: I do not want the nodes with null listed at all in the XML! The elements are set IsNullable = true in the class. Any suggestions as I have tried out many stuffs in Google.. nothing helped!

<?xml version="1.0" encoding="utf-8"?>
<Materials>
  <Material>
    <MaterialName>ABC</MaterialName>
    <Weight Value="0.303">
      <Weight_A xsi:nil="true" />
      <Weight_B xsi:nil="true" />
    </Weight>
    <Density Value="800">
      <Density_A xsi:nil="true" />
      <Density_B xsi:nil="true" />
    </Density>
    <Volume Value="8771.427" />
  </Material>
  <Material>
    <MaterialName>ABC</MaterialName>
    <Weight>
      <V5_Weight>2.009</V5_Weight>
      <V6_Weight>1.3318154561904</V6_Weight>
    </Weight>
    <Density>
      <V5_density>1000</V5_density>
      <V6_density>663</V6_density>
    </Density>
    <Volume Value="2008771.427" />
  </Material>
</Materials>

The class structure is as below:

[XmlRoot(ElementName = "Weight")]
public class Weight
{
    [XmlElement(ElementName = "Weight_A", IsNullable = true)]
    public string Weight_A { get; set; }

    [XmlElement(ElementName = "Weight_B", IsNullable = true)]
    public string Weight_B { get; set; }

    [XmlAttribute(AttributeName = "Value")]
    public string Value { get; set; }

}

[XmlRoot(ElementName = "Density")]
public class Density
{
    [XmlElement(ElementName = "Density_A", IsNullable = true)]
    public string Density_A { get; set; }
    [XmlElement(ElementName = "Density_B", IsNullable = true)]
    public string Density_B { get; set; }

    [XmlAttribute(AttributeName = "Value")]
    public string Value { get; set; }
}

[XmlRoot(ElementName = "Volume")]
public class Volume
{
    [XmlElement(ElementName = "Volume_A")]
    public string Volume_A { get; set; }
    [XmlElement(ElementName = "Volume_B")]
    public string Volume_B { get; set; }

    [XmlAttribute(AttributeName = "Value")]
    public string Value { get; set; }
}

[XmlRoot(ElementName = "Material")]
public class Material
{
    [XmlElement(ElementName = "MaterialName")]
    public string MaterialName { get; set; }
    [XmlElement(ElementName = "Weight")]
    public Weight Weight { get; set; }

    [XmlElement(ElementName = "Density")]
    public Density Density { get; set; }
    [XmlElement(ElementName = "Volume")]
    public Volume Volume { get; set; }
}

[XmlRoot(ElementName = "Materials")]
public class Materials
{
    [XmlElement(ElementName = "Material")]
    public List<Material> Material { get; set; }
}

回答1:


The basic issue is that you have set XmlElementAttribute.IsNullable = true. From the docs:

Gets or sets a value that indicates whether the XmlSerializer must serialize a member that is set to null as an empty tag with the xsi:nil attribute set to true.

Thus in theory you could just set it to be false (or don't set it at all) and the xsi:nil attributes will not be emitted for null values:

[XmlRoot(ElementName = "Weight")]
public class Weight
{
    [XmlElement(ElementName = "Weight_A" /*, IsNullable = true*/)]
    public string Weight_A { get; set; }
    [XmlElement(ElementName = "Weight_B" /*, IsNullable = true*/)]
    public string Weight_B { get; set; }

    [XmlAttribute(AttributeName = "Value")]
    public string Value { get; set; }
}

[XmlRoot(ElementName = "Density")]
public class Density
{
    [XmlElement(ElementName = "Density_A"/*, IsNullable = true*/)]
    public string Density_A { get; set; }
    [XmlElement(ElementName = "Density_B"/*, IsNullable = true*/)]
    public string Density_B { get; set; }

    [XmlAttribute(AttributeName = "Value")]
    public string Value { get; set; }
}

However, if you do that, you may encounter a problem deserializing legacy XML files, namely that string-valued xsi:nil elements will now get deserialized as empty strings rather than null strings. (Demo fiddle #1 here.) If this becomes a problem, you must leave the XmlElementAttribute.IsNullable = true setting and instead use the one of the conditional serialization patterns described in this answer to ShouldSerialize*() vs *Specified Conditional Serialization Pattern:

[XmlRoot(ElementName = "Weight")]
public class Weight
{
    [XmlElement(ElementName = "Weight_A", IsNullable = true)]
    public string Weight_A { get; set; }

    public bool ShouldSerializeWeight_A() { return Weight_A != null; }

    [XmlElement(ElementName = "Weight_B", IsNullable = true)]
    public string Weight_B { get; set; }

    public bool ShouldSerializeWeight_B() { return Weight_B != null; }

    [XmlAttribute(AttributeName = "Value")]
    public string Value { get; set; }
}

[XmlRoot(ElementName = "Density")]
public class Density
{
    [XmlElement(ElementName = "Density_A", IsNullable = true)]
    public string Density_A { get; set; }

    public bool ShouldSerializeDensity_A() { return Density_A != null; }

    [XmlElement(ElementName = "Density_B", IsNullable = true)]
    public string Density_B { get; set; }

    public bool ShouldSerializeDensity_B() { return Density_B != null; }

    [XmlAttribute(AttributeName = "Value")]
    public string Value { get; set; }
}

Having done this, the <NodeName xsi:nil="true" /> elements will get mapped to a null string during deserialization and skipped entirely during serialization.

Notes:

  • Your XML is not well-formed. It lacks a definition for the xsi: namespace prefix, perhaps because it's a fragment of some larger document. This answer assumes it should be:

    <Materials 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    
  • Some elements are not bound to your c# data model at all including:

    <V5_Weight>2.009</V5_Weight>
    <V6_Weight>1.3318154561904</V6_Weight>
    

    And

    <V5_density>1000</V5_density>
    <V6_density>663</V6_density>
    

    This answer does not attempt to address this problem (if it is, in fact, a problem).

Sample fiddle #2 here.



来源:https://stackoverflow.com/questions/52314031/remove-xml-element-with-xsinil-true-c-sharp-serialization

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!