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?
c#
.net
xml-serialization
NetSide
la source
la source
Réponses:
la source
s.Serialize(writer, objectToSerialize, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty }));
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.
Supposons que ce soit le type:
Voici comment vous utiliseriez une telle chose lors de la sérialisation:
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:
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:
Ensuite, fournissez une classe dérivée qui remplace la méthode StartElement, comme auparavant:
Et puis utilisez cet écrivain comme ceci:
Merci pour cela à Oleg Tkachenko .
la source
LookupPrefix(string ns)
pour toujours renvoyer une chaîne vide pour supprimer toutes les déclarations de schéma.XmlWriter
etXmlWriterSettings
.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
XmlSerializer
sérialisation XML intégrée et personnalisée viaIXmlSerialiazble
.Pour savoir, j'utiliserai le même
MyTypeWithNamespaces
exemple XML qui a été utilisé dans les réponses à cette question jusqu'à présent.C'est tout pour cette classe. Maintenant, certains se sont opposés à l'idée d'avoir un
XmlSerializerNamespaces
objet 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:
Une fois que vous avez fait cela, vous devriez obtenir le résultat suivant:
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
XmlSerializerNamespaces
membre 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émentantIXmlSerializable
.J'espère que cette réponse mettra fin, une fois pour toutes, à la manière de se débarrasser du standard
xsi
et desxsd
espaces de noms générés par leXmlSerializer
.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)Abracadbra
etWhoohoo
. 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,Abracadabra
est l'espace de noms defalt. Je pourrais dans maMyTypeWithNamespaces
classe ajouter un préfixe d'espace de noms pour l'Whoohoo
espace de noms comme ceci: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:É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 nomsxsi
etxsd
.la source
XmlWriter
qui est contenu dans leXmlMediaTypeFormatter
qui force les espaces de noms xsi et xsd dans ma sortie. Cela affecte uniquement ceux qui utilisent la valeur par défaut de WebApiXmlMediaTypeFormatter
. 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'XmlWriter
ajout automatique des deux valeurs par défaut. Voir cette réponseXmlSerializerNamespaces
décoré avec leXmlNamespacesDeclarationAttribute
. 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 leXmlSerializer
.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:
Et ce pseudo-code de sérialisation:
Vous obtiendrez quelque chose comme ce XML:
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:
Le résultat ressemble à ceci;
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.
la source
la source