使用 xsi:nil="true" C# 序列化删除 xml 元素
Remove xml element with xsi:nil="true" C# serialization
我有一个 XML,它有一些值,有时可能有空值,如下所示: 我根本不想在 XML 中列出空值的节点! class 中的元素设置为 IsNullable = true
。我在 Google 中尝试了很多东西时提出的任何建议都没有帮助!
<?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>
class结构如下:
[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; }
}
基本问题是你设置了XmlElementAttribute.IsNullable = true
。来自 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.
因此理论上你可以将它设置为 false(或者根本不设置它)并且 xsi:nil
属性不会为 null 值发出:
[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; }
}
但是,如果这样做,您可能会在反序列化遗留 XML 文件时遇到问题,即字符串值 xsi:nil
元素现在将被反序列化为空字符串,而不是 null
字符串。 (演示 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 to :
[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; }
}
完成此操作后,<NodeName xsi:nil="true" />
元素将在反序列化期间映射到 null
字符串,并在序列化期间完全跳过。
备注:
您的 XML 格式不正确。它缺少 xsi:
命名空间前缀的定义,可能是因为它是某个较大文档的片段。这个答案假设它应该是:
<Materials
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
有些元素根本没有绑定到您的 C# 数据模型,包括:
<V5_Weight>2.009</V5_Weight>
<V6_Weight>1.3318154561904</V6_Weight>
和
<V5_density>1000</V5_density>
<V6_density>663</V6_density>
这个答案并不试图解决这个问题(如果它实际上是一个问题)。
示例 fiddle #2 here.
我有一个 XML,它有一些值,有时可能有空值,如下所示: 我根本不想在 XML 中列出空值的节点! class 中的元素设置为 IsNullable = true
。我在 Google 中尝试了很多东西时提出的任何建议都没有帮助!
<?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>
class结构如下:
[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; }
}
基本问题是你设置了XmlElementAttribute.IsNullable = true
。来自 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.
因此理论上你可以将它设置为 false(或者根本不设置它)并且 xsi:nil
属性不会为 null 值发出:
[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; }
}
但是,如果这样做,您可能会在反序列化遗留 XML 文件时遇到问题,即字符串值 xsi:nil
元素现在将被反序列化为空字符串,而不是 null
字符串。 (演示 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
[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; }
}
完成此操作后,<NodeName xsi:nil="true" />
元素将在反序列化期间映射到 null
字符串,并在序列化期间完全跳过。
备注:
您的 XML 格式不正确。它缺少
xsi:
命名空间前缀的定义,可能是因为它是某个较大文档的片段。这个答案假设它应该是:<Materials xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
有些元素根本没有绑定到您的 C# 数据模型,包括:
<V5_Weight>2.009</V5_Weight> <V6_Weight>1.3318154561904</V6_Weight>
和
<V5_density>1000</V5_density> <V6_density>663</V6_density>
这个答案并不试图解决这个问题(如果它实际上是一个问题)。
示例 fiddle #2 here.