Omettre tous les espaces de noms xsi et xsd lors de la sérialisation d'un objet dans .NET?

132

Le code ressemble à ceci:

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

Le document sérialisé résultant comprend des espaces de noms, comme ceci:

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

Pour supprimer les espaces de noms xsi et xsd, je peux suivre la réponse de Comment sérialiser un objet en XML sans obtenir xmlns = ”…”? .

Je veux ma balise de message comme <message>(sans aucun attribut d'espace de noms). Comment puis-je faire ceci?

NetSide
la source
2
Je sais que vous pensez que cela pourrait améliorer votre xml, mais fournir des espaces de noms et des xsd correspondants est une meilleure pratique.
2
Je veux mon xml uniquement comme <message>, je parle d'omettre les espaces de noms xmlns: xsi et xmlns: xsd.
NetSide
5
Pour mémoire: en général, c'est une erreur insensée. Les espaces de noms sont là pour une raison, et les supprimer tous cassera les choses. Des choses comme la désérialisation.
John Saunders
66
Notez que parfois ce n'est pas stupide et pas une erreur. Par exemple, il peut être nécessaire de générer des fragments de document et de les assembler plus tard. Personnellement, j'avais besoin de générer beaucoup de documents similaires et très volumineux. Tous avaient les mêmes grandes parties au fond de l'arbre. J'ai donc dû générer au préalable les parties invariantes et les insérer sous forme de tableaux d'octets lors de la génération des documents. Donc, pour rendre la sortie plus lisible et plus petite, j'ai dû omettre certaines déclarations d'espaces de noms dans les parties internes car elles existaient aux niveaux supérieurs.
Dmitry Tashkinov

Réponses:

233
...
XmlSerializer s = new XmlSerializer(objectToSerialize.GetType());
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("","");
s.Serialize(xmlWriter, objectToSerialize, ns);
Thomas Levesque
la source
2
Je voudrais juste ajouter que la suppression de l'espace de noms par défaut peut avoir des conséquences inattendues: par exemple, si vous utilisez l'attribut XmlInclude pour sérialiser les types dérivés, les espaces de noms seront ajoutés à chacun de ces éléments, que vous le vouliez ou non, car ils sont nécessaires pour la désérialisation
Thomas Levesque
3
De plus, cela ne supprime pas tous les espaces de noms xml, comme la question posée. Il supprime uniquement les espaces de noms xsi et xsd, comme mentionné dans la question stackoverflow.com/questions/258960 , également citée dans cette question.
Cheeso
1
Pas non plus pris en charge par MS comme mentionné dans ma propre réponse. Il ne fonctionne pas toujours, surtout quand votre type peut être utilisé avec d' autres qui faire ont namespaces.
fourpastmidnight
@ThomasLevesque, comment supprimer l'espace de noms par défaut tout en utilisant l'attribut XmlInclude?
Jeson Martajaya
4
Peut être raccourci ens.Serialize(writer, objectToSerialize, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty }));
Xeevis
27

C'est la 2ème de deux réponses.

Si vous souhaitez simplement supprimer arbitrairement tous les espaces de noms d'un document pendant la sérialisation, vous pouvez le faire en implémentant votre propre XmlWriter.

Le moyen le plus simple consiste à dériver de XmlTextWriter et à remplacer la méthode StartElement qui émet des espaces de noms. La méthode StartElement est appelée par XmlSerializer lors de l'émission de tous les éléments, y compris la racine. En remplaçant l'espace de noms de chaque élément et en le remplaçant par la chaîne vide, vous avez supprimé les espaces de noms de la sortie.

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

Supposons que ce soit le type:

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

Voici comment vous utiliseriez une telle chose lors de la sérialisation:

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

Le XmlTextWriter est en quelque sorte cassé, cependant. Selon le document de référence , lorsqu'il écrit, il ne vérifie pas les éléments suivants:

  • Caractères non valides dans les noms d'attribut et d'élément.

  • Caractères Unicode qui ne correspondent pas au codage spécifié. Si les caractères Unicode ne correspondent pas au codage spécifié, XmlTextWriter n'échappe pas les caractères Unicode en entités de caractère.

  • Attributs en double.

  • Caractères de l'identifiant public DOCTYPE ou de l'identifiant système.

Ces problèmes avec XmlTextWriter existent depuis la v1.1 du .NET Framework, et ils resteront, pour des raisons de compatibilité descendante. Si vous n'avez aucune inquiétude à propos de ces problèmes, utilisez bien sûr XmlTextWriter. Mais la plupart des gens aimeraient un peu plus de fiabilité.

Pour obtenir cela, tout en supprimant les espaces de noms lors de la sérialisation, au lieu de dériver de XmlTextWriter, définissez une implémentation concrète du XmlWriter abstrait et de ses 24 méthodes.

Un exemple est ici:

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

Ensuite, fournissez une classe dérivée qui remplace la méthode StartElement, comme auparavant:

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

Et puis utilisez cet écrivain comme ceci:

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

Merci pour cela à Oleg Tkachenko .

Cheeso
la source
3
J'ai trouvé que j'avais également besoin de remplacer LookupPrefix(string ns)pour toujours renvoyer une chaîne vide pour supprimer toutes les déclarations de schéma.
Kevin Brock le
Cela ne répond pas techniquement à la question - vous utilisez XmlTextWriter, pas XmlWriter. Je remarque parce que je veux utiliser XmlWriter, pour les XmlWriterSettings que je peux utiliser avec.
Abacus
@Abacus avez-vous lu le code? Il utilise XmlWriter et XmlWriterSettings .
Cheeso
mon mauvais, j'ai dû manquer ça.
Abacus
Excellente réponse, en plus de la méthode ajoutée de @KevinBrock, j'avais également besoin de surcharger le <! - language: lang-cs -> WriteStartAttribute (préfixe de chaîne, chaîne localName, chaîne ns) avant que mon code ne supprime tout le espace de noms. Il convient également de noter que mes préfixes d'espaces de noms sont passés de b2p1 à p2, ce qui m'a conduit à rechercher d'autres méthodes utilisant des préfixes.
Mabdullah
15

Après avoir lu la documentation de Microsoft et plusieurs solutions en ligne, j'ai découvert la solution à ce problème. Il fonctionne avec la XmlSerializersérialisation XML intégrée et personnalisée via IXmlSerialiazble.

Pour savoir, j'utiliserai le même MyTypeWithNamespacesexemple XML qui a été utilisé dans les réponses à cette question jusqu'à présent.

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

C'est tout pour cette classe. Maintenant, certains se sont opposés à l'idée d'avoir un XmlSerializerNamespacesobjet quelque part dans leurs classes; mais comme vous pouvez le voir, je l'ai soigneusement rangé dans le constructeur par défaut et exposé une propriété publique pour renvoyer les espaces de noms.

Maintenant, quand vient le temps de sérialiser la classe, vous utiliserez le code suivant:

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

Une fois que vous avez fait cela, vous devriez obtenir le résultat suivant:

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

J'ai utilisé avec succès cette méthode dans un projet récent avec une hiérarchie profonde de classes sérialisées en XML pour les appels de service Web. La documentation de Microsoft n'est pas très claire sur ce qu'il faut faire avec le XmlSerializerNamespacesmembre accessible au public une fois que vous l'avez créé, et beaucoup pensent que c'est inutile. Mais en suivant leur documentation et en l'utilisant de la manière illustrée ci-dessus, vous pouvez personnaliser la façon dont XmlSerializer génère du XML pour vos classes sans recourir à un comportement non pris en charge ou «lancer votre propre» sérialisation en implémentant IXmlSerializable.

J'espère que cette réponse mettra fin, une fois pour toutes, à la manière de se débarrasser du standard xsiet des xsdespaces de noms générés par le XmlSerializer.

MISE À JOUR: Je veux juste m'assurer d'avoir répondu à la question du PO sur la suppression de tous les espaces de noms. Mon code ci-dessus fonctionnera pour cela; Laisse moi te montrer comment. Maintenant, dans l'exemple ci-dessus, vous ne pouvez vraiment pas vous débarrasser de tous les espaces de noms (car il y a deux espaces de noms en cours d'utilisation). Quelque part dans votre document XML, vous devrez avoir quelque chose comme xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo. Si la classe de l'exemple fait partie d'un document plus volumineux, alors quelque part au-dessus d'un espace de noms doit être déclaré pour l'un des (ou les deux) Abracadbraet Whoohoo. Sinon, l'élément dans l'un ou les deux espaces de noms doit être décoré avec un préfixe quelconque (vous ne pouvez pas avoir deux espaces de noms par défaut, n'est-ce pas?). Donc, pour cet exemple, Abracadabraest l'espace de noms defalt. Je pourrais dans ma MyTypeWithNamespacesclasse ajouter un préfixe d'espace de noms pour l' Whoohooespace de noms comme ceci:

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

Maintenant, dans ma définition de classe, j'ai indiqué que l' <Label/>élément est dans l'espace de noms "urn:Whoohoo", donc je n'ai rien à faire de plus. Lorsque je sérialise maintenant la classe en utilisant mon code de sérialisation ci-dessus inchangé, voici le résultat:

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

Étant donné qu'il se <Label>trouve dans un espace de noms différent du reste du document, il doit, en quelque sorte, être «décoré» d'un espace de noms. Notez qu'il n'y a toujours pas d' espaces de noms xsiet xsd.

quatre heures et demie
la source
"La documentation de Microsoft indique explicitement qu'elle n'est pas prise en charge." Envie de partager où?
Dave Van den Eynde
Dave, comme vous l'avez posté sur ma réponse à une question similaire, XmlSerializer: supprimez les espaces de noms xsi et xsd inutiles , le lien est ici: Classe XmlSerializerNamespaces .
fourpastmidnight
1
Vous passez toujours les espaces de noms à la méthode Serialize. Je pensais que l'idée de fournir un membre du public était que vous n'auriez pas à faire cela? Je ne peux pas le faire fonctionner sans le passer à la méthode Serialize. Et malheureusement, je n'ai pas accès à cet appel de méthode. Je ne peux définir que l'instance XmlSerializer à utiliser.
écraser le
J'ai trouvé que c'est en fait ce XmlWriterqui est contenu dans le XmlMediaTypeFormatterqui force les espaces de noms xsi et xsd dans ma sortie. Cela affecte uniquement ceux qui utilisent la valeur par défaut de WebApi XmlMediaTypeFormatter. J'ai copié le code source pour celui-ci et l'ai modifié pour transmettre ma propriété Namespaces à la méthode Serialize comme il le fallait pour empêcher l' XmlWriterajout automatique des deux valeurs par défaut. Voir cette réponse
écraser le
@crush, cette réponse à laquelle vous avez lié est trompeuse - pas fausse, mais ses affirmations ne sont pas toutes correctes. Si vous regardez le premier extrait de code dans ma réponse, vous verrez un commentaire qui indique explicitement le fonctionnement de XmlSerializer lorsque vous exposez un membre public de type XmlSerializerNamespacesdécoré avec le XmlNamespacesDeclarationAttribute. Cela a été pris directement à partir de MSDN et utilise essentiellement ces espaces de noms déclarés à la place de ceux par défaut fournis par le XmlSerializer.
fourpastmidnight
6

C'est la première de mes deux réponses à la question.

Si vous voulez un contrôle précis sur les espaces de noms - par exemple si vous voulez en omettre certains mais pas d'autres, ou si vous voulez remplacer un espace de noms par un autre, vous pouvez le faire en utilisant XmlAttributeOverrides .

Supposons que vous ayez cette définition de type:

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

Et ce pseudo-code de sérialisation:

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

Vous obtiendrez quelque chose comme ce XML:

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

Notez qu'il existe un espace de noms par défaut sur l'élément racine et qu'il existe également un espace de noms distinct sur l'élément "Label". Ces espaces de noms étaient dictés par les attributs décorant le type, dans le code ci-dessus.

Le framework de sérialisation Xml dans .NET inclut la possibilité de remplacer explicitement les attributs qui décorent le code réel. Vous faites cela avec la classe XmlAttributesOverrides et ses amis. Supposons que j'ai le même type et que je le sérialise de cette façon:

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

Le résultat ressemble à ceci;

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

Vous avez supprimé les espaces de noms.

Une question logique est la suivante: pouvez-vous supprimer tous les espaces de noms des types arbitraires pendant la sérialisation, sans passer par les remplacements explicites? La réponse est OUI, et comment le faire est dans ma prochaine réponse.

Cheeso
la source
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
la source