Сериализация без xmlns - PullRequest
14 голосов
/ 22 июня 2010

У меня есть пара методов расширения, которые обрабатывают сериализацию моих классов, и, поскольку это может занять много времени, они создаются один раз для каждого класса и передаются этим методом.

public static XmlSerializer GetSerializerFor(Type typeOfT)
{
    if (!serializers.ContainsKey(typeOfT))
    {
        var xmlAttributes = new XmlAttributes();
        var xmlAttributeOverrides = new XmlAttributeOverrides();

        System.Diagnostics.Debug.WriteLine(string.Format("XmlSerializerFactory.GetSerializerFor(typeof({0}));", typeOfT));

        xmlAttributes.Xmlns = false;
        xmlAttributeOverrides.Add(typeOfT, xmlAttributes);

        var newSerializer = new XmlSerializer(typeOfT, xmlAttributeOverrides);
        serializers.Add(typeOfT, newSerializer);
    }

    return serializers[typeOfT];
}

Это вызывается методом расширения .Serialize ()

public static XElement Serialize(this object source)
{
    try
    {
        var serializer = XmlSerializerFactory.GetSerializerFor(source.GetType());
        var xdoc = new XDocument();
        using (var writer = xdoc.CreateWriter())
        {
            serializer.Serialize(writer, source, new XmlSerializerNamespaces(new[] { new XmlQualifiedName("", "") }));
        }

        return (xdoc.Document != null) ? xdoc.Document.Root : new XElement("Error", "Document Missing");
    }
    catch (Exception x)
    {
        return new XElement("Error", x.ToString());
    }
}

К сожалению, при сериализации автоматически генерируемых классов к ним применяется атрибут XmlTypeAttribute(Namespace="http://tempuri.org/").

Это приводит к сбою десериализации неавтоматизированными аналогами.

Мне нужно, чтобы сериализатор полностью игнорировал и не применял пространство имен, но то, что я написал в первом блоке кода, похоже, не удаляет его, я все равно получаю xml как этот

<Note>
  <ID xmlns="http://tempuri.org/">12</ID>
  <Author xmlns="http://tempuri.org/">
    <ID>1234</ID>
    <Type>Associate</Type>
    <IsAvailable>false</IsAvailable>
  </Author>
  <Created xmlns="http://tempuri.org/">2010-06-22T09:38:01.5024351-05:00</Created>
  <Text xmlns="http://tempuri.org/">This is an update</Text>
</Note>

Вместо того же, минус атрибут xmlns="http://tempuri.org/".

Пожалуйста, помогите, спасибо, это сводит меня с ума!

EDIT:

Я знаю проблему, но не знаю, как ее исправить.

Мой класс не просто полон простых типов.

Содержит свойства с типами других классов. Которые также автоматически генерируются с атрибутом XmlTypeAttribute(Namespace = "http://tempuri.org/"). Итак, происходит то, что когда происходит сериализация, и она сериализует свойства моего класса, они не проходят через мою настраиваемую сериализацию, и, следовательно, атрибут применяется и не переопределяется.

Теперь мне просто нужно выяснить, как прыгнуть с этого обруча. Есть мысли о том, как?

РЕДАКТИРОВАТЬ 2:

Следующее работает для сериализации БЕЗ xmlns ... но у меня проблема с окончанием десериализации, но пока не уверен, связан он или нет

public static XmlSerializer GetSerializerFor(Type typeOfT)
{
    if (!serializers.ContainsKey(typeOfT))
    {
        var xmlAttributes = new XmlAttributes();
        var xmlAttributeOverrides = new XmlAttributeOverrides();

        System.Diagnostics.Debug.WriteLine(string.Format("XmlSerializerFactory.GetSerializerFor(typeof({0}));", typeOfT));

        xmlAttributes.XmlType = new XmlTypeAttribute
        {
            Namespace = ""
        };

        xmlAttributes.Xmlns = false;

        var types = new List<Type> {typeOfT, typeOfT.BaseType};

        foreach (var property in typeOfT.GetProperties())
        {
            types.Add(property.PropertyType);
        }

        types.RemoveAll(t => t.ToString().StartsWith("System."));

        foreach (var type in types)
        {
            xmlAttributeOverrides.Add(type, xmlAttributes);
        }

        var newSerializer = new XmlSerializer(typeOfT, xmlAttributeOverrides);
        //var newSerializer = new XmlSerializer(typeOfT, xmlAttributeOverrides, extraTypes.ToArray(), new XmlRootAttribute(), string.Empty);
        //var newSerializer = new XmlSerializer(typeOfT, string.Empty);

        serializers.Add(typeOfT, newSerializer);
    }

    return serializers[typeOfT];
}

EDIT3: Закончилось использованием решения от Как удалить все пространства имен из XML с помощью C #?

public static XElement RemoveAllNamespaces(this XElement source)
{
    return !source.HasElements
               ? new XElement(source.Name.LocalName)
                     {
                         Value = source.Value
                     }
               : new XElement(source.Name.LocalName, source.Elements().Select(el => RemoveAllNamespaces(el)));
}

Ответы [ 3 ]

49 голосов
/ 16 декабря 2011

Рабочий раствор, для записи!

var ns = new XmlSerializerNamespaces();
ns.Add("", ""); 
var serializer = new XmlSerializer(yourType); 
serializer.Serialize(xmlTextWriter, someObject, ns);
4 голосов
/ 22 июня 2010

Нет проблем - просто передайте пустую строку в качестве пространства имен по умолчанию для сериализатора XML:

XmlSerializer newSerializer = 
   new XmlSerializer(typeOfT, "");

К сожалению, нет легкой перегрузки конструктора, если вам действительно нужно определить XmlAttributeOverrides и пространство имен по умолчанию - так что вы можете либо пропустить XmlAttributeOverrides и использовать тот конструктор, который я упомянул, либо вам нужен тот, который определяет все возможные параметры (включая XmlAttributeOverrides и пространства имен XML по умолчанию - и некоторые другие).

1 голос
/ 21 марта 2014
 public static byte[] SerializeByteByType(object objectToSerialize, Type type)
    {
        XmlWriterSettings xmlSetting = new XmlWriterSettings()
        {
            NewLineOnAttributes = false,
            OmitXmlDeclaration = true,
            Indent = false,
            NewLineHandling = NewLineHandling.None,
            Encoding = Encoding.UTF8,
            NamespaceHandling = NamespaceHandling.OmitDuplicates
        };

        using (MemoryStream stm = new MemoryStream())
        {
            using (XmlWriter writer = XmlWriter.Create(stm, xmlSetting))
            {
                var xmlAttributes = new XmlAttributes();
                var xmlAttributeOverrides = new XmlAttributeOverrides();

                xmlAttributes.Xmlns = false;
                xmlAttributes.XmlType = new XmlTypeAttribute() { Namespace = "" };
                xmlAttributeOverrides.Add(type, xmlAttributes);

                XmlSerializer serializer = new XmlSerializer(type, xmlAttributeOverrides);
                //Use the following to serialize without namespaces
                XmlSerializerNamespaces xmlSrzNamespace = new XmlSerializerNamespaces();
                xmlSrzNamespace.Add("", "");

                serializer.Serialize(writer, objectToSerialize, xmlSrzNamespace);
                stm.Flush();
                stm.Position = 0;
            }

            return stm.ToArray();
        }
    }         
...