¿Omitiendo todos los espacios de nombres xsi y xsd al serializar un objeto en .NET?

132

El código se ve así:

StringBuilder builder = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
using (XmlWriter xmlWriter = XmlWriter.Create(builder, settings))
{
    XmlSerializer s = new XmlSerializer(objectToSerialize.GetType());
    s.Serialize(xmlWriter, objectToSerialize);
}

El documento serializado resultante incluye espacios de nombres, así:

<message xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 
    xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" 
    xmlns="urn:something">
 ...
</message>

Para eliminar los espacios de nombres xsi y xsd, puedo seguir la respuesta de ¿Cómo serializar un objeto a XML sin obtener xmlns = "..."? .

Quiero mi etiqueta de mensaje como <message>(sin ningún atributo de espacio de nombres). ¿Cómo puedo hacer esto?

NetSide
fuente
2
Sé que piensas que esto podría hacer que tu xml se vea mejor, pero proporcionar espacios de nombres y xsd correspondientes es una mejor práctica.
2
Quiero mi xml solo como <message>, estoy hablando de omitir xmlns: xsi y xmlns: xsd namespaces.
NetSide
55
Para el registro: en general, este es un error tonto. Los espacios de nombres están ahí por una razón, y eliminarlos todos romperá las cosas. Cosas como la deserialización.
John Saunders
66
Tenga en cuenta que a veces no es tonto y no es un error. Por ejemplo, uno puede necesitar generar fragmentos de documentos y armarlos más tarde. Personalmente, necesitaba generar muchos documentos similares y muy grandes. Todos ellos tenían las mismas partes grandes en lo profundo del árbol. Así que tuve que generar las partes invariantes de antemano e insertarlas como conjuntos de bytes al generar los documentos. Entonces, para hacer que la salida sea más legible y más pequeña, necesitaba omitir algunas declaraciones de espacios de nombres en las partes internas porque existían en los niveles superiores.
Dmitry Tashkinov

Respuestas:

233
...
XmlSerializer s = new XmlSerializer(objectToSerialize.GetType());
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("","");
s.Serialize(xmlWriter, objectToSerialize, ns);
Thomas Levesque
fuente
2
Solo me gustaría agregar que eliminar el espacio de nombres predeterminado puede tener consecuencias no deseadas: por ejemplo, si usa el atributo XmlInclude para serializar los tipos derivados, los espacios de nombres se agregarán a cada uno de estos elementos, lo quiera o no, porque son necesarios para la deserialización
Thomas Levesque
3
Además, esto no elimina todos los espacios de nombres xml, como se hizo la pregunta. Solo elimina los espacios de nombres xsi y xsd, como se menciona en la pregunta stackoverflow.com/questions/258960 , que también se cita en esta pregunta.
Cheeso
1
Tampoco es compatible con MS como se menciona en mi propia respuesta. No siempre funciona, sobre todo cuando su tipo puede ser utilizado con otros que hacer tienen espacios de nombres.
fourpastmidnight
@ThomasLevesque, ¿cómo eliminar el espacio de nombres predeterminado mientras se usa el atributo XmlInclude?
Jeson Martajaya
44
Se puede acortar as.Serialize(writer, objectToSerialize, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty }));
Xeevis
27

Esta es la segunda de dos respuestas.

Si desea eliminar todos los espacios de nombres de forma arbitraria de un documento durante la serialización, puede hacerlo implementando su propio XmlWriter.

La forma más fácil es derivar de XmlTextWriter y anular el método StartElement que emite espacios de nombres. XmlSerializer invoca el método StartElement al emitir cualquier elemento, incluida la raíz. Al anular el espacio de nombres para cada elemento y reemplazarlo con la cadena vacía, ha eliminado los espacios de nombres de la salida.

public class NoNamespaceXmlWriter : XmlTextWriter
{
    //Provide as many contructors as you need
    public NoNamespaceXmlWriter(System.IO.TextWriter output)
        : base(output) { Formatting= System.Xml.Formatting.Indented;}

    public override void WriteStartDocument () { }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        base.WriteStartElement("", localName, "");
    }
}

Supongamos que este es el tipo:

// explicitly specify a namespace for this type,
// to be used during XML serialization.
[XmlRoot(Namespace="urn:Abracadabra")]
public class MyTypeWithNamespaces
{
    // private fields backing the properties
    private int _Epoch;
    private string _Label;

    // explicitly define a distinct namespace for this element
    [XmlElement(Namespace="urn:Whoohoo")]
    public string Label
    {
        set {  _Label= value; } 
        get { return _Label; } 
    }

    // this property will be implicitly serialized to XML using the
    // member name for the element name, and inheriting the namespace from
    // the type.
    public int Epoch
    {
        set {  _Epoch= value; } 
        get { return _Epoch; } 
    }
}

Así es como usaría tal cosa durante la serialización:

        var o2= new MyTypeWithNamespaces { ..intializers.. };
        var builder = new System.Text.StringBuilder();
        using ( XmlWriter writer = new NoNamespaceXmlWriter(new System.IO.StringWriter(builder)))
        {
            s2.Serialize(writer, o2, ns2);
        }            
        Console.WriteLine("{0}",builder.ToString());

Sin embargo, XmlTextWriter está roto. Según el documento de referencia , cuando escribe no verifica lo siguiente:

  • Caracteres no válidos en los atributos y nombres de elementos.

  • Caracteres Unicode que no se ajustan a la codificación especificada. Si los caracteres Unicode no se ajustan a la codificación especificada, XmlTextWriter no escapa de los caracteres Unicode a las entidades de caracteres.

  • Atributos duplicados.

  • Caracteres en el identificador público DOCTYPE o el identificador del sistema.

Estos problemas con XmlTextWriter han existido desde la v1.1 de .NET Framework, y seguirán siendo compatibles con versiones anteriores. Si no le preocupan esos problemas, entonces utilice XmlTextWriter. Pero a la mayoría de la gente le gustaría un poco más de fiabilidad.

Para obtener eso, mientras suprime los espacios de nombres durante la serialización, en lugar de derivar de XmlTextWriter, defina una implementación concreta del resumen XmlWriter y sus 24 métodos.

Un ejemplo está aquí:

public class XmlWriterWrapper : XmlWriter
{
    protected XmlWriter writer;

    public XmlWriterWrapper(XmlWriter baseWriter)
    {
        this.Writer = baseWriter;
    }

    public override void Close()
    {
        this.writer.Close();
    }

    protected override void Dispose(bool disposing)
    {
        ((IDisposable) this.writer).Dispose();
    }

    public override void Flush()
    {
        this.writer.Flush();
    }

    public override string LookupPrefix(string ns)
    {
        return this.writer.LookupPrefix(ns);
    }

    public override void WriteBase64(byte[] buffer, int index, int count)
    {
        this.writer.WriteBase64(buffer, index, count);
    }

    public override void WriteCData(string text)
    {
        this.writer.WriteCData(text);
    }

    public override void WriteCharEntity(char ch)
    {
        this.writer.WriteCharEntity(ch);
    }

    public override void WriteChars(char[] buffer, int index, int count)
    {
        this.writer.WriteChars(buffer, index, count);
    }

    public override void WriteComment(string text)
    {
        this.writer.WriteComment(text);
    }

    public override void WriteDocType(string name, string pubid, string sysid, string subset)
    {
        this.writer.WriteDocType(name, pubid, sysid, subset);
    }

    public override void WriteEndAttribute()
    {
        this.writer.WriteEndAttribute();
    }

    public override void WriteEndDocument()
    {
        this.writer.WriteEndDocument();
    }

    public override void WriteEndElement()
    {
        this.writer.WriteEndElement();
    }

    public override void WriteEntityRef(string name)
    {
        this.writer.WriteEntityRef(name);
    }

    public override void WriteFullEndElement()
    {
        this.writer.WriteFullEndElement();
    }

    public override void WriteProcessingInstruction(string name, string text)
    {
        this.writer.WriteProcessingInstruction(name, text);
    }

    public override void WriteRaw(string data)
    {
        this.writer.WriteRaw(data);
    }

    public override void WriteRaw(char[] buffer, int index, int count)
    {
        this.writer.WriteRaw(buffer, index, count);
    }

    public override void WriteStartAttribute(string prefix, string localName, string ns)
    {
        this.writer.WriteStartAttribute(prefix, localName, ns);
    }

    public override void WriteStartDocument()
    {
        this.writer.WriteStartDocument();
    }

    public override void WriteStartDocument(bool standalone)
    {
        this.writer.WriteStartDocument(standalone);
    }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        this.writer.WriteStartElement(prefix, localName, ns);
    }

    public override void WriteString(string text)
    {
        this.writer.WriteString(text);
    }

    public override void WriteSurrogateCharEntity(char lowChar, char highChar)
    {
        this.writer.WriteSurrogateCharEntity(lowChar, highChar);
    }

    public override void WriteValue(bool value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(DateTime value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(decimal value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(double value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(int value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(long value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(object value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(float value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteValue(string value)
    {
        this.writer.WriteValue(value);
    }

    public override void WriteWhitespace(string ws)
    {
        this.writer.WriteWhitespace(ws);
    }


    public override XmlWriterSettings Settings
    {
        get
        {
            return this.writer.Settings;
        }
    }

    protected XmlWriter Writer
    {
        get
        {
            return this.writer;
        }
        set
        {
            this.writer = value;
        }
    }

    public override System.Xml.WriteState WriteState
    {
        get
        {
            return this.writer.WriteState;
        }
    }

    public override string XmlLang
    {
        get
        {
            return this.writer.XmlLang;
        }
    }

    public override System.Xml.XmlSpace XmlSpace
    {
        get
        {
            return this.writer.XmlSpace;
        }
    }        
}

Luego, proporcione una clase derivada que anule el método StartElement, como antes:

public class NamespaceSupressingXmlWriter : XmlWriterWrapper
{
    //Provide as many contructors as you need
    public NamespaceSupressingXmlWriter(System.IO.TextWriter output)
        : base(XmlWriter.Create(output)) { }

    public NamespaceSupressingXmlWriter(XmlWriter output)
        : base(XmlWriter.Create(output)) { }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        base.WriteStartElement("", localName, "");
    }
}

Y luego usa este escritor así:

        var o2= new MyTypeWithNamespaces { ..intializers.. };
        var builder = new System.Text.StringBuilder();
        var settings = new XmlWriterSettings { OmitXmlDeclaration = true, Indent= true };
        using ( XmlWriter innerWriter = XmlWriter.Create(builder, settings))
            using ( XmlWriter writer = new NamespaceSupressingXmlWriter(innerWriter))
            {
                s2.Serialize(writer, o2, ns2);
            }            
        Console.WriteLine("{0}",builder.ToString());

Gracias por esto a Oleg Tkachenko .

Cheeso
fuente
3
Descubrí que también necesitaba anular LookupPrefix(string ns)para devolver siempre una cadena vacía para eliminar todas las declaraciones de esquema.
Kevin Brock
Esto técnicamente no responde la pregunta: está utilizando XmlTextWriter, no XmlWriter. Me doy cuenta porque quiero usar XmlWriter, para XmlWriterSettings que puedo usar con él.
Abacus
@Abacus, ¿leíste el código? Utiliza XmlWriter y XmlWriterSettings .
Cheeso
mi mal, debo haberme perdido eso.
Abacus
Gran respuesta, además del método agregado de @KevinBrock, también necesitaba sobrecargar el <! - language: lang-cs -> WriteStartAttribute (prefijo de cadena, cadena localName, cadena ns) antes de que mi código elimine todos los espacio de nombres También vale la pena señalar que mis prefijos de espacio de nombres estaban cambiando de b2p1 a p2, lo que me llevó a buscar otros métodos usando prefijos.
Mabdullah
15

Después de leer la documentación de Microsoft y varias soluciones en línea, descubrí la solución a este problema. Funciona con la XmlSerializerserialización XML incorporada y personalizada a través de IXmlSerialiazble.

A saber, utilizaré la misma MyTypeWithNamespacesmuestra XML que se ha utilizado en las respuestas a esta pregunta hasta ahora.

[XmlRoot("MyTypeWithNamespaces", Namespace="urn:Abracadabra", IsNullable=false)]
public class MyTypeWithNamespaces
{
    // As noted below, per Microsoft's documentation, if the class exposes a public
    // member of type XmlSerializerNamespaces decorated with the 
    // XmlNamespacesDeclarationAttribute, then the XmlSerializer will utilize those
    // namespaces during serialization.
    public MyTypeWithNamespaces( )
    {
        this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {
            // Don't do this!! Microsoft's documentation explicitly says it's not supported.
            // It doesn't throw any exceptions, but in my testing, it didn't always work.

            // new XmlQualifiedName(string.Empty, string.Empty),  // And don't do this:
            // new XmlQualifiedName("", "")

            // DO THIS:
            new XmlQualifiedName(string.Empty, "urn:Abracadabra") // Default Namespace
            // Add any other namespaces, with prefixes, here.
        });
    }

    // If you have other constructors, make sure to call the default constructor.
    public MyTypeWithNamespaces(string label, int epoch) : this( )
    {
        this._label = label;
        this._epoch = epoch;
    }

    // An element with a declared namespace different than the namespace
    // of the enclosing type.
    [XmlElement(Namespace="urn:Whoohoo")]
    public string Label
    {
        get { return this._label; }
        set { this._label = value; }
    }
    private string _label;

    // An element whose tag will be the same name as the property name.
    // Also, this element will inherit the namespace of the enclosing type.
    public int Epoch
    {
        get { return this._epoch; }
        set { this._epoch = value; }
    }
    private int _epoch;

    // Per Microsoft's documentation, you can add some public member that
    // returns a XmlSerializerNamespaces object. They use a public field,
    // but that's sloppy. So I'll use a private backed-field with a public
    // getter property. Also, per the documentation, for this to work with
    // the XmlSerializer, decorate it with the XmlNamespaceDeclarations
    // attribute.
    [XmlNamespaceDeclarations]
    public XmlSerializerNamespaces Namespaces
    {
        get { return this._namespaces; }
    }
    private XmlSerializerNamespaces _namespaces;
}

Eso es todo para esta clase. Ahora, algunos se opusieron a tener un XmlSerializerNamespacesobjeto en algún lugar dentro de sus clases; pero como puede ver, lo guardé cuidadosamente en el constructor predeterminado y expuse una propiedad pública para devolver los espacios de nombres.

Ahora, cuando llegue el momento de serializar la clase, usaría el siguiente código:

MyTypeWithNamespaces myType = new MyTypeWithNamespaces("myLabel", 42);

/******
   OK, I just figured I could do this to make the code shorter, so I commented out the
   below and replaced it with what follows:

// You have to use this constructor in order for the root element to have the right namespaces.
// If you need to do custom serialization of inner objects, you can use a shortened constructor.
XmlSerializer xs = new XmlSerializer(typeof(MyTypeWithNamespaces), new XmlAttributeOverrides(),
    new Type[]{}, new XmlRootAttribute("MyTypeWithNamespaces"), "urn:Abracadabra");

******/
XmlSerializer xs = new XmlSerializer(typeof(MyTypeWithNamespaces),
    new XmlRootAttribute("MyTypeWithNamespaces") { Namespace="urn:Abracadabra" });

// I'll use a MemoryStream as my backing store.
MemoryStream ms = new MemoryStream();

// This is extra! If you want to change the settings for the XmlSerializer, you have to create
// a separate XmlWriterSettings object and use the XmlTextWriter.Create(...) factory method.
// So, in this case, I want to omit the XML declaration.
XmlWriterSettings xws = new XmlWriterSettings();
xws.OmitXmlDeclaration = true;
xws.Encoding = Encoding.UTF8; // This is probably the default
// You could use the XmlWriterSetting to set indenting and new line options, but the
// XmlTextWriter class has a much easier method to accomplish that.

// The factory method returns a XmlWriter, not a XmlTextWriter, so cast it.
XmlTextWriter xtw = (XmlTextWriter)XmlTextWriter.Create(ms, xws);
// Then we can set our indenting options (this is, of course, optional).
xtw.Formatting = Formatting.Indented;

// Now serialize our object.
xs.Serialize(xtw, myType, myType.Namespaces);

Una vez que haya hecho esto, debería obtener el siguiente resultado:

<MyTypeWithNamespaces>
    <Label xmlns="urn:Whoohoo">myLabel</Label>
    <Epoch>42</Epoch>
</MyTypeWithNamespaces>

He utilizado con éxito este método en un proyecto reciente con una gran jerarquía de clases que se serializan en XML para llamadas de servicio web. La documentación de Microsoft no es muy clara sobre qué hacer con el XmlSerializerNamespacesmiembro de acceso público una vez que lo ha creado, y muchos piensan que es inútil. Pero siguiendo su documentación y usándola de la manera que se muestra arriba, puede personalizar cómo XmlSerializer genera XML para sus clases sin recurrir a comportamientos no admitidos o "rodar su propia" serialización mediante la implementación IXmlSerializable.

Espero que esta respuesta deje de lado, de una vez por todas, cómo deshacerse del estándar xsiy los xsdespacios de nombres generados por XmlSerializer.

ACTUALIZACIÓN: Solo quiero asegurarme de haber respondido la pregunta del OP sobre la eliminación de todos los espacios de nombres. Mi código anterior funcionará para esto; Déjame enseñarte como. Ahora, en el ejemplo anterior, realmente no puede deshacerse de todos los espacios de nombres (porque hay dos espacios de nombres en uso). En algún lugar de su documento XML, necesitará tener algo como esto xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo. Si la clase en el ejemplo es parte de un documento más grande, entonces se debe declarar en algún lugar sobre un espacio de nombres para uno de (o ambos) Abracadbray Whoohoo. De lo contrario, el elemento en uno o en ambos espacios de nombres debe estar decorado con un prefijo de algún tipo (no puede tener dos espacios de nombres predeterminados, ¿verdad?). Entonces, para este ejemplo, Abracadabraes el espacio de nombres defalt. Podría dentro de mi MyTypeWithNamespacesclase agregar un prefijo de espacio de nombres para el Whoohooespacio de nombres de esta manera:

public MyTypeWithNamespaces
{
    this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {
        new XmlQualifiedName(string.Empty, "urn:Abracadabra"), // Default Namespace
        new XmlQualifiedName("w", "urn:Whoohoo")
    });
}

Ahora, en mi definición de clase, indiqué que el <Label/>elemento está en el espacio de nombres "urn:Whoohoo", por lo que no necesito hacer nada más. Cuando ahora serializo la clase usando mi código de serialización anterior sin cambios, esta es la salida:

<MyTypeWithNamespaces xmlns:w="urn:Whoohoo">
    <w:Label>myLabel</w:Label>
    <Epoch>42</Epoch>
</MyTypeWithNamespaces>

Debido a que <Label>está en un espacio de nombres diferente del resto del documento, debe, de alguna manera, estar "decorado" con un espacio de nombres. Tenga en cuenta que todavía no hay espacios de nombres xsiy xsd.

fourpastmidnight
fuente
"La documentación de Microsoft dice explícitamente que no es compatible". ¿Te importa compartir dónde?
Dave Van den Eynde
Dave, como publicaste en mi respuesta a una pregunta similar, XmlSerializer: elimina los espacios de nombres xsi y xsd innecesarios , el enlace está aquí: XmlSerializerNamespaces Class .
fourpastmidnight
1
Todavía está pasando los espacios de nombres al método Serialize. Pensé que la idea de proporcionar un miembro público era que no tendrías que hacer eso. Sin embargo, no puedo hacerlo funcionar sin pasarlo al método Serialize. Y desafortunadamente, no tengo acceso a esa llamada al método. Solo puedo configurar la instancia de XmlSerializer para usar.
aplastar
Descubrí que en realidad XmlWriteres lo que está contenido en lo XmlMediaTypeFormatterque fuerza los espacios de nombres xsi y xsd en mi salida independientemente. Esto solo afecta a quienes usan el valor predeterminado de WebApi XmlMediaTypeFormatter. Copié el código fuente y lo modifiqué para pasar mi propiedad de espacios de nombres al método Serialize, ya que era necesario para evitar que XmlWriteragregaran automáticamente los dos valores predeterminados. Ver esta respuesta
aplastar
@crush, esa respuesta a la que se vinculó es engañosa, no está mal, pero sus afirmaciones no son todas correctas. Si observa el primer fragmento de código en mi respuesta, verá un comentario que indica explícitamente cómo funciona XmlSerializer cuando expone un miembro público de tipo XmlSerializerNamespacesdecorado con el XmlNamespacesDeclarationAttribute. Esto fue tomado directamente de MSDN y esencialmente usa esos espacios de nombres declarados en lugar de los predeterminados proporcionados por XmlSerializer.
fourpastmidnight el
6

Esta es la primera de mis dos respuestas a la pregunta.

Si desea un control preciso sobre los espacios de nombres, por ejemplo, si desea omitir algunos de ellos pero no otros, o si desea reemplazar un espacio de nombres con otro, puede hacerlo utilizando XmlAttributeOverrides .

Supongamos que tiene esta definición de tipo:

// explicitly specify a namespace for this type,
// to be used during XML serialization.
[XmlRoot(Namespace="urn:Abracadabra")]
public class MyTypeWithNamespaces
{
    // private fields backing the properties
    private int _Epoch;
    private string _Label;

    // explicitly define a distinct namespace for this element
    [XmlElement(Namespace="urn:Whoohoo")]
    public string Label
    {
        set {  _Label= value; } 
        get { return _Label; } 
    }

    // this property will be implicitly serialized to XML using the
    // member name for the element name, and inheriting the namespace from
    // the type.
    public int Epoch
    {
        set {  _Epoch= value; } 
        get { return _Epoch; } 
    }
}

Y este pseudocódigo de serialización:

        var o2= new MyTypeWithNamespaces() { ..initializers...};
        ns.Add( "", "urn:Abracadabra" );
        XmlSerializer s2 = new XmlSerializer(typeof(MyTypeWithNamespaces));
        s2.Serialize(System.Console.Out, o2, ns);

Obtendría algo como este XML:

<MyTypeWithNamespaces xmlns="urn:Abracadabra">
  <Label xmlns="urn:Whoohoo">Cimsswybclaeqjh</Label>
  <Epoch>97</Epoch>
</MyTypeWithNamespaces>

Observe que hay un espacio de nombres predeterminado en el elemento raíz, y también hay un espacio de nombres distinto en el elemento "Etiqueta". Estos espacios de nombres fueron dictados por los atributos que decoran el tipo, en el código anterior.

El marco de serialización Xml en .NET incluye la posibilidad de anular explícitamente los atributos que decoran el código real. Lo haces con la clase XmlAttributesOverrides y amigos. Supongamos que tengo el mismo tipo y lo serializo de esta manera:

        // instantiate the container for all attribute overrides
        XmlAttributeOverrides xOver = new XmlAttributeOverrides();

        // define a set of XML attributes to apply to the root element
        XmlAttributes xAttrs1 = new XmlAttributes();

        // define an XmlRoot element (as if [XmlRoot] had decorated the type)
        // The namespace in the attribute override is the empty string. 
        XmlRootAttribute xRoot = new XmlRootAttribute() { Namespace = ""};

        // add that XmlRoot element to the container of attributes
        xAttrs1.XmlRoot= xRoot;

        // add that bunch of attributes to the container holding all overrides
        xOver.Add(typeof(MyTypeWithNamespaces), xAttrs1);

        // create another set of XML Attributes
        XmlAttributes xAttrs2 = new XmlAttributes();

        // define an XmlElement attribute, for a type of "String", with no namespace
        var xElt = new XmlElementAttribute(typeof(String)) { Namespace = ""};

        // add that XmlElement attribute to the 2nd bunch of attributes
        xAttrs2.XmlElements.Add(xElt);

        // add that bunch of attributes to the container for the type, and
        // specifically apply that bunch to the "Label" property on the type.
        xOver.Add(typeof(MyTypeWithNamespaces), "Label", xAttrs2);

        // instantiate a serializer with the overrides 
        XmlSerializer s3 = new XmlSerializer(typeof(MyTypeWithNamespaces), xOver);

        // serialize
        s3.Serialize(System.Console.Out, o2, ns2);

El resultado se ve así;

<MyTypeWithNamespaces>
  <Label>Cimsswybclaeqjh</Label>
  <Epoch>97</Epoch>
</MyTypeWithNamespaces>

Has eliminado los espacios de nombres.

Una pregunta lógica es, ¿ puede eliminar todos los espacios de nombres de tipos arbitrarios durante la serialización, sin pasar por las anulaciones explícitas? La respuesta es SÍ, y cómo hacerlo está en mi próxima respuesta.

Cheeso
fuente
6
XmlSerializer sr = new XmlSerializer(objectToSerialize.GetType());
TextWriter xmlWriter = new StreamWriter(filename);
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);
sr.Serialize(xmlWriter, objectToSerialize, namespaces);
Tejas
fuente