我在可序列化类中添加了一些可以为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存储过程,所以我也避免更改我的类。我正在对.value()查询中的所有可空元素进行[not(@xsi:nil)]
检查。
我发现ABCS指定的公共bool是唯一一个使用.NET 4.0的公共bool。我还必须添加XmlIgnoreAttribute
这是我在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;
}
}
像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;
}
我必须为每个可空值添加一个ShouldSerialize
方法。
[Serializable]
public class Parent
{
public int? Element { get; set; }
public bool ShouldSerializeElement() => Element.HasValue;
}
这可能是最不复杂的答案,但是我用简单的字符串替换解决了它。
.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\" ", "");
}
}
}