问题
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 thexsi: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