2010-06-22 15 views
14

Tengo un par de métodos de extensión que manejan la serialización de mis clases, y dado que puede ser un proceso lento, se crean una vez por clase y se reparten por este método.Serializar SIN 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.Xmlns = false; 
     xmlAttributeOverrides.Add(typeOfT, xmlAttributes); 

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

    return serializers[typeOfT]; 
} 

Esto es llamado por el método de extensión .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()); 
    } 
} 

Por desgracia, cuando serialización de clases que son auto-generado, que tienen el atributo XmlTypeAttribute(Namespace="http://tempuri.org/") que se les aplica.

Esto provoca que la deserialización por parte de las contrapartes no generadas automáticamente falle.

necesito el serializador ignorar por completo y no aplicar el espacio de nombres, pero lo que he escrito en el primer bloque de código no parece que quitarlo, que aún así terminar con XML como esto

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

En lugar de lo mismo, menos el atributo xmlns="http://tempuri.org/".

Por favor, ayuda, gracias, esto me está volviendo loco!

EDIT:

Sé que el problema, pero no cómo solucionarlo.

Mi clase no solo está llena de tipos simples.

Contiene propiedades con tipos de otras clases. Que también se generan automáticamente con el atributo XmlTypeAttribute(Namespace = "http://tempuri.org/"). Entonces, lo que está sucediendo es que cuando ocurre la serialización y serializa las propiedades de mi clase, no están pasando por mi serialización personalizada, y por lo tanto, están teniendo el atributo aplicado y no anulado.

Ahora solo necesito descubrir cómo saltar ese aro. ¿Alguna idea de cómo?

EDIT 2:

las siguientes obras para serializar SIN xmlns ... pero estoy teniendo un problema en el extremo deserialización, por el momento no está seguro de si está relacionado o no

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 : acabaron utilizando solución de How to remove all namespaces from XML with 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))); 
} 
+1

su última solución debería haber sido nombrado 'RemoveAllAttributes' – redtetrahedron

Respuesta

3

No hay problema - sólo tiene que pasar una cadena vacía como el predeterminado espacio de nombres al serializador XML:

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

Por desgracia, no hay fácil sobrecarga de constructor si realmente se necesita para definir el XmlAttributeOverrides y el espacio de nombres por defecto - por lo que tampoco se puede omitir el XmlAttributeOverrides y utilizar ese constructor he mencionado, o si necesita usar el que define todos los parámetros posibles (incluyendo XmlAttributeOverrides y espacios de nombres XML predeterminados, y algunos más).

+0

que es lo que tenía antes de que realmente, no funcionó, todavía estaba usando el valor de la XmlTypeAttribute en la clase. Y probé lo siguiente y no funcionó ni 'var newSerializer = new XmlSerializer (typeOfT, xmlAttributeOverrides, new Type [] {}, new XmlRootAttribute()," ");' – CaffGeek

+0

string.Empty >>> "" :) – annakata

+0

@annakata, también he intentado reemplazarlo con string.Empty. – CaffGeek

44

Una solución de trabajo, para el registro!

var ns = new XmlSerializerNamespaces(); 
ns.Add("", ""); 
var serializer = new XmlSerializer(yourType); 
serializer.Serialize(xmlTextWriter, someObject, ns); 
+0

Sin duda una mejor solución. ¡Funciona de maravilla! – user460762

+10

Para el registro, esto eliminará 'xsi' y' xsd', pero agregará un nuevo 'xmlns: prefix = ' y agregará el prefijo a todas sus etiquetas si tiene 'XmlTypeAttribute's con espacios de nombres especificados en su clases – redtetrahedron

+0

Esto realmente funcionó perfecto para mí, después de probar tantas cosas diferentes que simplemente no hacen el trabajo sin efectos secundarios. Muchas gracias. – JoeFox

1
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(); 
     } 
    }   
+0

En su lugar "xmlAttributeOverrides.Add (type, xmlAttributes);" debe ser: "var tipos = type.Assembly.GetTypes() Donde (t => string.Equals (t.Namespace, currentType.Namespace, StringComparison.Ordinal)); XmlAttributeOverrides var = nuevos XmlAttributeOverrides(); \t \t \t. foreach (var t en tipos) \t xmlAttributeOverrides.Add (t, xmlAttributes); " – Mentor

Cuestiones relacionadas