我在我的可序列化类中添加了一些可为空的值类型。我使用执行序列化,XmlSerializer
但是当值设置为 时null
,我得到一个空节点xsi:nil="true"
。这是我在Xsi:nil Attribute Binding Support找到的正确行为。
有没有办法关闭此选项,以便在值类型为 时不输出任何内容null
?
我在我的可序列化类中添加了一些可为空的值类型。我使用执行序列化,XmlSerializer
但是当值设置为 时null
,我得到一个空节点xsi:nil="true"
。这是我在Xsi:nil Attribute Binding Support找到的正确行为。
有没有办法关闭此选项,以便在值类型为 时不输出任何内容null
?
我遇到了同样的问题..这是我读到的关于在序列化为 XML 时处理可为空值类型的地方之一:http ://stackoverflow.com/questions/244953/serialize-a-nullable-int
他们提到使用内置模式,例如为可空值类型创建附加属性。就像一个名为
public int? ABC
你必须要么添加要么public bool ShouldSerializeABC() {return ABC.HasValue;}
公开bool ABCSpecified { get { return ABC.HasValue; } }
我只是序列化到 xml 以发送到 sql 存储过程,所以我也避免更改我的类。我正在[not(@xsi:nil)]
检查 .value() 查询中的所有可空元素。
我必须为ShouldSerialize
每个可为空的值添加一个方法。
[Serializable]
public class Parent
{
public int? Element { get; set; }
public bool ShouldSerializeElement() => Element.HasValue;
}
我发现 public bool ABCSpecified 是唯一一个与 .NET 4.0 一起工作的。我还必须添加 XmlIgnoreAttribute
这是我在 Web Reference Resource.cs 文件中抑制名为 ABC 的字符串的完整解决方案:
// backing fields
private string abc;
private bool abcSpecified; // Added this - for client code to control its serialization
// serialization of properties
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
public string ABC
{
get
{
return this.abc;
}
set
{
this.abc= value;
}
}
// Added this entire property procedure
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool ABCSpecified
{
get
{
return this.abcSpecified;
}
set
{
this.abcSpecified = value;
}
}
这可能是最不复杂的答案,但我通过简单的字符串替换为我解决了这个问题。
.Replace(" xsi:nil=\"true\" ", "");
无论如何,我首先要序列化为字符串。我可以稍后保存到文件中。
它使我所有的 XmlWriterSettings 保持不变。我发现她搞砸的另一种解决方案:)
private static string Serialize<T>(T details)
{
var serializer = new XmlSerializer(typeof(T));
using (var ms = new MemoryStream())
{
var settings = new XmlWriterSettings
{
Encoding = Encoding.GetEncoding("ISO-8859-1"),
NewLineChars = Environment.NewLine,
ConformanceLevel = ConformanceLevel.Document,
Indent = true,
OmitXmlDeclaration = true
};
using (var writer = XmlWriter.Create(ms, settings))
{
serializer.Serialize(writer, details);
return Encoding.UTF8.GetString(ms.ToArray()).Replace(" xsi:nil=\"true\" ", "");
}
}
}
Specified或ShouldSerialize等所有元方法只是 Microsoft .Net XML 结构的糟糕编程设计。如果您无法直接访问要序列化的类,情况会变得更加复杂。
在他们的序列化方法中,他们应该只添加一个像“ignoreNullable”这样的属性。
我当前的解决方法是序列化 xml,然后使用以下函数删除所有具有nil="true"的节点。
/// <summary>
/// Remove optional nullabe xml nodes from given xml string using given scheme prefix.
///
/// In other words all nodes that have 'xsi:nil="true"' are being removed from document.
///
/// If prefix 'xmlns:xsi' is not found in root element namespace input xml content is returned.
/// </summary>
/// <param name="xmlContent"></param>
/// <param name="schemePrefix">Scheme location prefix</param>
/// <returns></returns>
public static String RemoveNilTrue(String xmlContent, String schemePrefix = "xsi")
{
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xmlContent);
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmlDocument.NameTable);
bool schemeExist = false;
foreach (XmlAttribute attr in xmlDocument.DocumentElement.Attributes)
{
if (attr.Prefix.Equals("xmlns", StringComparison.InvariantCultureIgnoreCase)
&& attr.LocalName.Equals(schemePrefix, StringComparison.InvariantCultureIgnoreCase))
{
nsMgr.AddNamespace(attr.LocalName, attr.Value);
schemeExist = true;
break;
}
}
// scheme exists - remove nodes
if (schemeExist)
{
XmlNodeList xmlNodeList = xmlDocument.SelectNodes("//*[@" + schemePrefix + ":nil='true']", nsMgr);
foreach (XmlNode xmlNode in xmlNodeList)
xmlNode.ParentNode.RemoveChild(xmlNode);
return xmlDocument.InnerXml;
}
else
return xmlContent;
}
我是这样完成的:
private bool retentionPeriodSpecified;
private Nullable<int> retentionPeriod;
[XmlElement(ElementName = "retentionPeriod", IsNullable = true, Order = 14)]
public Nullable<int> RetentionPeriod { get => retentionPeriod; set => retentionPeriod = value; }
[System.Xml.Serialization.XmlIgnore()]
public bool RetentionPeriodSpecified
{
get { return !(retentionPeriod is null); }
}