防止 在序列化为XML时的可空值类型

问题描述 投票:8回答:5

我在可序列化类中添加了一些可以为null的值类型。我使用XmlSerializer执行序列化,但是当值设置为null时,我得到一个带xsi:nil="true"的空节点。这是我在Xsi:nil Attribute Binding Support找到的正确行为。

有没有办法关闭此选项,以便在值类型为null时不输出任何内容?

.net serialization xml-serialization xml-nil
5个回答
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)]检查。


4
投票

我发现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;
    }
}

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;
}

1
投票

我必须为每个可空值添加一个ShouldSerialize方法。

[Serializable]
public class Parent
{
    public int? Element { get; set; }

    public bool ShouldSerializeElement() => Element.HasValue;
}

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\" ", "");
            }
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.