Omitindo todos os namespaces xsi e xsd ao serializar um objeto no .NET?

132

O código fica assim:

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

O documento serializado resultante inclui espaços para nome, assim:

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

Para remover os namespaces xsi e xsd, posso seguir a resposta em Como serializar um objeto para XML sem obter xmlns = ”…”? .

Quero minha tag de mensagem como <message>(sem nenhum atributo de espaço para nome). Como posso fazer isso?

NetSide
fonte
2
Eu sei que você acha que isso pode fazer com que seu xml pareça melhor, mas fornecer namespaces e xsd correspondentes é uma prática melhor.
2
Eu quero meu xml apenas como <mensage>, estou falando sobre omitir namespaces xmlns: xsi e xmlns: xsd.
9/09 NetSide
5
Para constar: em geral, este é um erro tolo. Os namespaces estão lá por um motivo, e removê-los todos quebrará as coisas. Coisas como desserialização.
318 John Saunders
66
Note que às vezes não é tolice e nem um erro. Por exemplo, pode ser necessário gerar fragmentos de documento e reuni-los mais tarde. Pessoalmente, eu precisava gerar muitos documentos semelhantes e muito grandes. Todos eles tinham as mesmas partes grandes no fundo da árvore. Portanto, tive que gerar as partes invariantes antecipadamente e inseri-las como matrizes de bytes ao gerar os documentos. Portanto, para tornar a saída mais legível e menor, eu precisava omitir algumas declarações de namespace nas partes internas porque elas existiam nos níveis mais altos.
Dmitry Tashkinov

Respostas:

233
...
XmlSerializer s = new XmlSerializer(objectToSerialize.GetType());
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("","");
s.Serialize(xmlWriter, objectToSerialize, ns);
Thomas Levesque
fonte
2
Gostaria apenas de acrescentar que a remoção do espaço para nome padrão pode ter consequências indesejadas: por exemplo, se você usar o atributo XmlInclude para serializar tipos derivados, os espaços para nome serão adicionados a cada um desses elementos, quer você queira ou não, porque eles 're necessário para desserialização
Thomas Levesque
3
Além disso, isso não remove todos os espaços para nome xml, conforme a pergunta. Ele remove apenas os namespaces xsi e xsd, conforme mencionado na pergunta stackoverflow.com/questions/258960 , que também é citada nesta pergunta.
Cheeso
1
Também não é suportado pelo MS, como mencionado na minha própria resposta. Nem sempre funciona, especialmente quando o seu tipo pode ser usado com outros que fazem tem namespaces.
Fourpastmidnight
@ThomasLevesque, como remover o espaço para nome padrão ao usar o atributo XmlInclude?
Jeson Martajaya
4
Pode ser reduzido paras.Serialize(writer, objectToSerialize, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty }));
Xeevis
27

Esta é a segunda de duas respostas.

Se você deseja remover todos os namespaces arbitrariamente de um documento durante a serialização, pode fazer isso implementando seu próprio XmlWriter.

A maneira mais fácil é derivar do XmlTextWriter e substituir o método StartElement que emite espaços para nome. O método StartElement é chamado pelo XmlSerializer ao emitir qualquer elemento, incluindo a raiz. Substituindo o espaço para nome de cada elemento e substituindo-o pela string vazia, você removeu os espaços para nome da saída.

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

Suponha que este seja o 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; } 
    }
}

Aqui está como você usaria isso durante a serialização:

        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());

O XmlTextWriter está meio que quebrado, no entanto. De acordo com o documento de referência , ao escrever, não verifica o seguinte:

  • Caracteres inválidos nos nomes de atributos e elementos.

  • Caracteres Unicode que não se ajustam à codificação especificada. Se os caracteres Unicode não couberem na codificação especificada, o XmlTextWriter não escapará dos caracteres Unicode nas entidades de caracteres.

  • Atributos duplicados.

  • Caracteres no identificador público DOCTYPE ou identificador do sistema.

Esses problemas com o XmlTextWriter existem desde a v1.1 do .NET Framework e permanecerão para compatibilidade com versões anteriores. Se você não tiver preocupações com esses problemas, use o XmlTextWriter. Mas a maioria das pessoas gostaria de um pouco mais de confiabilidade.

Para conseguir isso, enquanto ainda suprime os espaços para nome durante a serialização, em vez de derivar do XmlTextWriter, defina uma implementação concreta do XmlWriter abstrato e de seus 24 métodos.

Um exemplo está aqui:

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

Em seguida, forneça uma classe derivada que substitua o 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, "");
    }
}

E então use este escritor assim:

        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());

Crédito por isso a Oleg Tkachenko .

Cheeso
fonte
3
Descobri que também precisava substituir LookupPrefix(string ns)para sempre retornar uma string vazia para remover todas as declarações de esquema.
22412 Kevin Brock
Tecnicamente, isso não responde à pergunta - você está usando o XmlTextWriter, não o XmlWriter. Percebo porque quero usar o XmlWriter, para o XmlWriterSettings que posso usar com ele.
quer
@Abacus você leu o código? Ele usa XmlWriter e XmlWriterSettings .
Cheeso
meu mal, eu devo ter perdido isso.
Abacus
Ótima resposta, além do método adicionado de @ KevinBrock, eu também precisei sobrecarregar o <! - language: lang-cs -> WriteStartAttribute (prefixo, string localName, string ns) antes que meu código removesse todo o namespacing. Também digno de nota, meus prefixos de namespace estavam mudando de b2p1 para p2, o que me levou a procurar outros métodos usando prefixos.
Mabdullah
15

Depois de ler a documentação da Microsoft e várias soluções online, descobri a solução para esse problema. Ele funciona com a XmlSerializerserialização XML interna e personalizada via IXmlSerialiazble.

Ou seja, usarei a mesma MyTypeWithNamespacesamostra XML usada nas respostas até agora.

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

Isso é tudo nessa classe. Agora, alguns se opuseram a ter um XmlSerializerNamespacesobjeto em algum lugar dentro de suas classes; mas, como você pode ver, coloquei-o ordenadamente no construtor padrão e expus uma propriedade pública para retornar os namespaces.

Agora, quando chegar a hora de serializar a classe, você usaria o seguinte 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);

Depois de fazer isso, você deverá obter a seguinte saída:

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

Usei esse método com êxito em um projeto recente com uma hierarquia profunda de classes serializadas em XML para chamadas de serviço da web. A documentação da Microsoft não é muito clara sobre o que fazer com o XmlSerializerNamespacesmembro publicamente acessível depois que você a criou, e muitos pensam que é inútil. Porém, seguindo a documentação e usando-a da maneira mostrada acima, você pode personalizar como o XmlSerializer gera XML para suas classes sem recorrer a um comportamento não suportado ou a serialização "rolando sua própria" implementandoIXmlSerializable .

Espero que esta resposta descanse, de uma vez por todas, como se livrar do padrão xsie dos xsdnamespaces gerados pelo XmlSerializer.

ATUALIZAÇÃO: Eu só quero ter certeza de que respondi à pergunta do OP sobre como remover todos os espaços para nome. Meu código acima funcionará para isso; Deixa-me mostrar-te como. Agora, no exemplo acima, você realmente não pode se livrar de todos os namespaces (porque existem dois namespaces em uso). Em algum lugar do seu documento XML, você precisará ter algo parecido xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo. Se a classe no exemplo fizer parte de um documento maior, algum lugar acima de um espaço para nome deverá ser declarado para um (ou ambos) Abracadbrae Whoohoo. Caso contrário, o elemento em um ou em ambos os espaços para nome deve ser decorado com um prefixo de algum tipo (você não pode ter dois espaços para nome padrão, certo?). Portanto, para este exemplo, Abracadabraé o namespace defalt. Eu poderia dentro da minha MyTypeWithNamespacesclasse adicionar um prefixo de namespace para o Whoohoonamespace da seguinte forma:

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

Agora, na minha definição de classe, indiquei que o <Label/>elemento está no espaço "urn:Whoohoo"para nome , portanto, não preciso fazer mais nada. Quando agora serializo a classe usando meu código de serialização acima inalterado, esta é a saída:

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

Como <Label>está em um espaço para nome diferente do restante do documento, ele deve, de alguma maneira, ser "decorado" com um espaço para nome. Observe que ainda não existem espaços para nome xsie xsd.

meia-noite
fonte
"A documentação da Microsoft diz explicitamente que não é suportada." Gostaria de compartilhar onde?
Dave Van den Eynde
Dave, como você postou na minha resposta a uma pergunta semelhante, XmlSerializer: remova desnecessários namespaces xsi e xsd , o link está aqui: XmlSerializerNamespaces Class .
Fourpastmidnight
1
Você ainda está passando os espaços para nome para o método Serialize. Eu pensei que a idéia de fornecer um membro público era que você não precisaria fazer isso? Eu não consigo fazê-lo funcionar sem passar para o método Serialize. E, infelizmente, não tenho acesso a essa chamada de método. Só posso definir a instância XmlSerializer para usar.
esmagar
Eu descobri que é realmente o XmlWriterque está contido no XmlMediaTypeFormatterque força os namespaces xsi e xsd na minha saída independentemente. Isso afeta apenas aqueles que usam o padrão da WebApi XmlMediaTypeFormatter. Copiei o código-fonte e modifiquei-o para passar minha propriedade Namespaces para o método Serialize, conforme necessário, para impedir a XmlWriteradição automática dos dois padrões. Veja esta resposta
esmaga
@crush, essa resposta à qual você está vinculado é enganosa - não errada, mas suas afirmações não estão todas corretas. Se você olhar o primeiro trecho de código na minha resposta, verá um comentário que afirma explicitamente como o XmlSerializer funciona quando você expõe um membro público do tipo XmlSerializerNamespacesdecorado com o XmlNamespacesDeclarationAttribute. Isso foi tirado diretamente do MSDN e, essencialmente, usa os espaços para nome declarados no lugar dos espaços padrão fornecidos pelo XmlSerializer.
Fourpastmidnight
6

Esta é a primeira das minhas duas respostas à pergunta.

Se você deseja um controle fino sobre os espaços para nome - por exemplo, se deseja omitir alguns deles, mas não outros, ou se deseja substituir um espaço para nome por outro, você pode fazer isso usando XmlAttributeOverrides .

Suponha que você tenha esta definição 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; } 
    }
}

E esse pseudo-código de serialização:

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

Você obteria algo como este XML:

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

Observe que há um espaço para nome padrão no elemento raiz e também um espaço para nome distinto no elemento "Label". Esses namespaces foram determinados pelos atributos que decoram o tipo, no código acima.

A estrutura de serialização de XML no .NET inclui a possibilidade de substituir explicitamente os atributos que decoram o código real. Você faz isso com a classe XmlAttributesOverrides e amigos. Suponha que eu tenha o mesmo tipo e eu o serialize desta maneira:

        // 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);

O resultado é assim;

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

Você removeu os espaços para nome.

Uma pergunta lógica é: você pode retirar todos os namespaces de tipos arbitrários durante a serialização, sem passar pelas substituições explícitas? A resposta é SIM, e como fazê-lo está na minha próxima resposta.

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