我在可序列化类中添加了一些可以为null的值类型。我使用XmlSerializer
执行序列化,但是当值设置为null
时,我得到一个xsi:nil="true"
的空节点。这是我在Xsi:nil Attribute Binding Support找到的正确行为。
有没有办法关闭此选项,以便在值类型为null
时不输出任何内容?
答案 0 :(得分:5)
我遇到了同样的问题..这是我在序列化为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存储过程,所以我也避免更改我的类。我正在对{.value()查询中的所有可空元素进行[not(@xsi:nil)]
检查。
答案 1 :(得分:4)
以下是我在Web Reference Resource.cs文件中禁止名为ABC的String的完整解决方案:
// 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;
}
}
答案 2 :(得分:1)
所有的元方法,如 Specified 或 ShouldSerialize ,只是一个糟糕的微软.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;
}
答案 3 :(得分:1)
我必须向每个可为空的值添加一个ShouldSerialize
方法。
[Serializable]
public class Parent
{
public int? Element { get; set; }
public bool ShouldSerializeElement() => Element.HasValue;
}
答案 4 :(得分:0)
这可能是最不复杂的答案,但是我用一个简单的字符串替换就解决了它。
.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\" ", "");
}
}
}
答案 5 :(得分:0)
我是这样完成的:
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); }
}