Запретить <xsi: nil = "true"> для типов значений Nullable при сериализации в XML - PullRequest
8 голосов
/ 12 февраля 2010

Я добавил некоторые типы значений Nullable в мой сериализуемый класс. Я выполняю сериализацию, используя XmlSerializer, но когда установлено значение null, я получаю пустой узел с xsi:nil="true". Это правильное поведение, как я обнаружил в Xsi: nil Поддержка привязки атрибутов .

Есть ли способ отключить эту опцию, чтобы ничего не выводилось при типе значения null?

Ответы [ 5 ]

5 голосов
/ 06 июня 2010

У меня была такая же проблема ... вот одно из мест, где я читал об обработке типов значений Nullable при сериализации в XML: /191080/serializirovat-obnulyaemyi-int

они упоминают об использовании встроенных шаблонов, таких как создание дополнительных свойств для типов значений Nullable. как для свойства с именем

public int? ABC

вы должны либо добавить либо public bool ShouldSerializeABC() {return ABC.HasValue;} или общедоступный bool ABCSpecified { get { return ABC.HasValue; } }

Я только сериализовал в xml для отправки в сохраненный в SQL процесс, поэтому я тоже избегал менять свои классы. Я делаю [not(@xsi:nil)] проверку всех обнуляемых элементов в моем запросе .value ().

4 голосов
/ 15 апреля 2011

Я обнаружил, что публичный бул ABCS уточнил был единственным, который работал с .NET 4.0. Мне также пришлось добавить XmlIgnoreAttribute

Вот мое полное решение для подавления строки с именем ABC в файле веб-ссылки Resource.cs:

// 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 голосов
/ 31 августа 2018

Мне нужно было добавить ShouldSerialize метод к каждому значению, которое можно обнулять.

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

    public bool ShouldSerializeElement() => Element.HasValue;
}
1 голос
/ 28 ноября 2017

Все мета-методы, такие как Заданный или 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;
}
0 голосов
/ 28 февраля 2018

Это, вероятно, наименее сложный ответ, но я решил его для меня простой заменой строки.

.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\" ", "");
            }
        }
    }
...