Omettere tutti gli spazi dei nomi xsi e xsd durante la serializzazione di un oggetto in .NET?


132

Il codice è simile al seguente:

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

Il documento serializzato risultante include spazi dei nomi, in questo modo:

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

Per rimuovere gli spazi dei nomi xsi e xsd, posso seguire la risposta da Come serializzare un oggetto in XML senza ottenere xmlns = "..."? .

Voglio il mio tag messaggio come <message>(senza alcun attributo dello spazio dei nomi). Come posso fare questo?


2
So che pensi che questo potrebbe far apparire meglio il tuo xml, ma fornire spazi dei nomi e corrispondenti xsd è una pratica migliore.

2
Voglio il mio xml solo come <message>, sto parlando di omettere xmlns: xsi e xmlns: xsd namespace.
NetSide

5
Per la cronaca: in generale, questo è un errore folle. Gli spazi dei nomi sono lì per un motivo e rimuoverli tutti spezzerà le cose. Cose come la deserializzazione.
John Saunders,

66
Nota che a volte non è sciocco e non è un errore. Ad esempio, potrebbe essere necessario generare frammenti di documento e metterli insieme in un secondo momento. Personalmente, dovevo generare molti documenti simili e molto grandi. Tutti avevano le stesse grandi parti in profondità all'interno dell'albero. Quindi ho dovuto generare in anticipo le parti invarianti e inserirle come array di byte durante la generazione dei documenti. Quindi, per rendere l'output più leggibile e più piccolo, avevo bisogno di omettere alcune dichiarazioni dello spazio dei nomi nelle parti interne perché esistevano ai livelli più alti.
Dmitry Tashkinov,

Risposte:


233
...
XmlSerializer s = new XmlSerializer(objectToSerialize.GetType());
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("","");
s.Serialize(xmlWriter, objectToSerialize, ns);

2
Vorrei solo aggiungere che la rimozione dello spazio dei nomi predefinito può avere conseguenze non intenzionali: ad esempio, se si utilizza l'attributo XmlInclude per serializzare i tipi derivati, gli spazi dei nomi verranno aggiunti a ciascuno di questi elementi, che lo si voglia o no, perché sono necessari per la deserializzazione
Thomas Levesque,

3
Inoltre, questo non rimuove tutti gli spazi dei nomi xml, come la domanda posta. Rimuove solo gli spazi dei nomi xsi e xsd, come indicato nella domanda stackoverflow.com/questions/258960 , citata anche in questa domanda.
Cheeso,

1
Inoltre, non è supportato dalla SM, come indicato nella mia risposta. Non sempre funziona, soprattutto quando il tuo tipo può essere usato con altri che fare avere spazi dei nomi.
fourpastmidnight,

@ThomasLevesque, come rimuovere lo spazio dei nomi predefinito durante l'utilizzo dell'attributo XmlInclude?
Jeson Martajaya,

4
Può essere abbreviato ins.Serialize(writer, objectToSerialize, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty }));
Xeevis il

27

Questa è la seconda delle due risposte.

Se si desidera eliminare arbitrariamente tutti gli spazi dei nomi da un documento durante la serializzazione, è possibile farlo implementando il proprio XmlWriter.

Il modo più semplice è derivare da XmlTextWriter e sovrascrivere il metodo StartElement che emette spazi dei nomi. Il metodo StartElement viene invocato da XmlSerializer quando si emettono elementi, incluso il root. Sovrascrivendo lo spazio dei nomi per ciascun elemento e sostituendolo con la stringa vuota, hai rimosso gli spazi dei nomi dall'output.

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

Supponiamo che questo sia il 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; } 
    }
}

Ecco come useresti una cosa del genere durante la serializzazione:

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

Tuttavia, XmlTextWriter è in qualche modo rotto. Secondo il documento di riferimento , quando scrive non verifica quanto segue:

  • Caratteri non validi nei nomi degli attributi e degli elementi.

  • Caratteri Unicode che non si adattano alla codifica specificata. Se i caratteri Unicode non si adattano alla codifica specificata, XmlTextWriter non sfugge ai caratteri Unicode nelle entità carattere.

  • Attributi duplicati.

  • Caratteri nell'identificatore pubblico DOCTYPE o nell'identificatore di sistema.

Questi problemi con XmlTextWriter sono presenti dalla v1.1 di .NET Framework e rimarranno per compatibilità con le versioni precedenti. Se non hai dubbi su questi problemi, usa sicuramente XmlTextWriter. Ma la maggior parte delle persone vorrebbe un po 'più di affidabilità.

Per ottenere ciò, pur sopprimendo gli spazi dei nomi durante la serializzazione, anziché derivare da XmlTextWriter, definire un'implementazione concreta dell'astratto XmlWriter e dei suoi 24 metodi.

Un esempio è qui:

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

Quindi, fornire una classe derivata che sovrascrive il metodo StartElement, come in precedenza:

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 quindi usa questo writer in questo modo:

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

Ringraziamo questo per Oleg Tkachenko .


3
Ho scoperto che avevo anche bisogno di eseguire l'override LookupPrefix(string ns)per restituire sempre una stringa vuota per rimuovere tutte le dichiarazioni dello schema.
Kevin Brock,

Questo tecnicamente non risponde alla domanda: stai usando XmlTextWriter, non XmlWriter. Noto perché voglio usare XmlWriter, per le XmlWriterSettings che posso usare con esso.
Abacus,

@Abacus hai letto il codice? Usa XmlWriter e XmlWriterSettings .
Cheeso,

mio male, devo averlo perso.
Abacus,

Ottima risposta, Oltre al metodo aggiunto da @KevinBrock, avevo anche bisogno di sovraccaricare la <! - lingua: lang-cs -> WriteStartAttribute (prefisso stringa, stringa localName, stringa ns) prima che il mio codice eliminasse tutto il namespacing. Vale anche la pena notare che i miei prefissi dello spazio dei nomi stavano cambiando da b2p1 a p2, il che mi ha portato a verificare altri metodi usando i prefissi.
Mabdullah,

15

Dopo aver letto la documentazione di Microsoft e diverse soluzioni online, ho scoperto la soluzione a questo problema. Funziona con la XmlSerializerserializzazione XML integrata e personalizzata tramite IXmlSerialiazble.

Per intenderci, userò lo stesso MyTypeWithNamespacescampione XML che è stato usato finora nelle risposte a questa domanda.

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

Questo è tutto per questa classe. Ora, alcuni hanno obiettato di avere unXmlSerializerNamespaces oggetto da qualche parte all'interno delle loro classi; ma come puoi vedere, l'ho riposto ordinatamente nel costruttore predefinito ed esposto una proprietà pubblica per restituire gli spazi dei nomi.

Ora, quando arriva il momento di serializzare la classe, useresti il ​​seguente codice:

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 volta fatto questo, dovresti ottenere il seguente output:

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

Ho usato con successo questo metodo in un recente progetto con una profonda gerarchia di classi serializzate in XML per le chiamate al servizio web. La documentazione di Microsoft non è molto chiara su cosa fare con il XmlSerializerNamespacesmembro accessibile pubblicamente dopo averlo creato, e così tanti pensano che sia inutile. Ma seguendo la loro documentazione e utilizzandola nel modo mostrato sopra, puoi personalizzare il modo in cui XmlSerializer genera XML per le tue classi senza ricorrere a comportamenti non supportati o "far rotolare la tua" serializzazione implementandoIXmlSerializable .

Spero che questa risposta ponga fine, una volta per tutte, a come sbarazzarsi dello standard xsie degli xsdspazi dei nomi generati da XmlSerializer.

AGGIORNAMENTO: Voglio solo assicurarmi di aver risposto alla domanda del PO sulla rimozione di tutti gli spazi dei nomi. Il mio codice sopra funzionerà per questo; lascia che ti mostri come. Ora, nell'esempio sopra, non puoi davvero sbarazzarti di tutti gli spazi dei nomi (perché ci sono due spazi dei nomi in uso). Da qualche parte nel tuo documento XML, dovrai avere qualcosa di simile xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo. Se la classe nell'esempio fa parte di un documento più grande, allora da qualche parte sopra uno spazio dei nomi deve essere dichiarato per uno di (o entrambi) Abracadbrae Whoohoo. In caso contrario, l'elemento in uno o entrambi gli spazi dei nomi deve essere decorato con un prefisso di qualche tipo (non è possibile avere due spazi dei nomi predefiniti, giusto?). Quindi, per questo esempio, Abracadabraè lo spazio dei nomi defalt. Potrei all'interno della mia MyTypeWithNamespacesclasse aggiungere un prefisso dello Whoohoospazio dei nomi per lo spazio dei nomi in questo modo:

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

Ora, nella mia definizione di classe, ho indicato che l' <Label/>elemento si trova nello spazio dei nomi "urn:Whoohoo", quindi non ho bisogno di fare altro. Quando ora serializzo la classe usando il mio codice di serializzazione sopra invariato, questo è l'output:

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

Poiché si <Label>trova in uno spazio dei nomi diverso dal resto del documento, deve, in qualche modo, essere "decorato" con uno spazio dei nomi. Si noti che non ci sono ancora xsie xsdspazi dei nomi.


"La documentazione di Microsoft afferma esplicitamente che non è supportata." Vuoi condividere dove?
Dave Van den Eynde,

Dave, come hai pubblicato sulla mia risposta a una domanda simile, XmlSerializer: rimuovi gli spazi dei nomi inutili xsi e xsd , il link è qui: Classe XmlSerializerNamespaces .
fourpastmidnight,

1
Stai ancora passando gli spazi dei nomi al metodo Serialize. Pensavo che l'idea di fornire un membro pubblico fosse che non avresti dovuto farlo? Non riesco a farlo funzionare senza passare al metodo Serialize. E sfortunatamente, non ho accesso a quella chiamata di metodo. Posso solo impostare l'istanza XmlSerializer da usare.
schiaccia

Ho scoperto che in realtà XmlWriterè quello contenuto nel fileXmlMediaTypeFormatter che forza gli spazi dei nomi xsi e xsd nel mio output, indipendentemente. Ciò riguarda solo quelli che utilizzano l'impostazione predefinita di WebApi XmlMediaTypeFormatter. Ho copiato il codice sorgente per esso e l'ho modificato per passare la mia proprietà Namespaces al metodo Serialize come richiesto per impedire l' XmlWriteraggiunta automatica dei due valori predefiniti. Vedi questa risposta
schiaccia il

@crush, quella risposta a cui ti sei collegato è fuorviante - non sbagliata, ma le sue affermazioni non sono tutte corrette. Se guardi il primo frammento di codice nella mia risposta, vedrai un commento che afferma esplicitamente come funziona XmlSerializer quando esponi un membro pubblico di tipo XmlSerializerNamespacesdecorato con XmlNamespacesDeclarationAttribute. Questo è stato preso direttamente da MSDN e utilizza essenzialmente gli spazi dei nomi dichiarati al posto di quelli predefiniti forniti da XmlSerializer.
fourpastmidnight

6

Questa è la prima delle mie due risposte alla domanda.

Se si desidera un controllo accurato degli spazi dei nomi, ad esempio se si desidera ometterne alcuni, ma non altri, o se si desidera sostituire uno spazio dei nomi con un altro, è possibile farlo utilizzando XmlAttributeOverrides .

Supponiamo di avere questa definizione di 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 questo pseudo-codice di serializzazione:

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

Otterresti qualcosa di simile a questo XML:

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

Si noti che esiste uno spazio dei nomi predefinito sull'elemento radice e che esiste anche uno spazio dei nomi distinto sull'elemento "Etichetta". Questi spazi dei nomi sono stati dettati dagli attributi che decorano il tipo, nel codice sopra.

Il framework di serializzazione Xml in .NET include la possibilità di sovrascrivere esplicitamente gli attributi che decorano il codice effettivo. Puoi farlo con la classe XmlAttributesOverrides e gli amici. Supponiamo di avere lo stesso tipo e di serializzarlo in questo modo:

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

Il risultato è simile al seguente;

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

Hai spogliato gli spazi dei nomi.

Una domanda logica è: puoi rimuovere tutti gli spazi dei nomi da tipi arbitrari durante la serializzazione, senza passare attraverso le sostituzioni esplicite? La risposta è SÌ, e come farlo è nella mia prossima risposta.


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);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.