Der Code sieht folgendermaßen aus:
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);
}
Das resultierende serialisierte Dokument enthält Namespaces wie folgt:
<message xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"
xmlns="urn:something">
...
</message>
Um die Namespaces xsi und xsd zu entfernen, kann ich der Antwort unter So serialisieren Sie ein Objekt in XML folgen , ohne xmlns = ”…” zu erhalten. .
Ich möchte mein Nachrichten-Tag als <message>
(ohne Namespace-Attribute). Wie kann ich das machen?
c#
.net
xml-serialization
NetSide
quelle
quelle
Antworten:
quelle
s.Serialize(writer, objectToSerialize, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty }));
Dies ist die 2. von zwei Antworten.
Wenn Sie während der Serialisierung nur alle Namespaces willkürlich aus einem Dokument entfernen möchten, können Sie dies tun, indem Sie Ihren eigenen XmlWriter implementieren.
Am einfachsten ist es, von XmlTextWriter abzuleiten und die StartElement-Methode zu überschreiben, die Namespaces ausgibt. Die StartElement-Methode wird vom XmlSerializer aufgerufen, wenn Elemente einschließlich des Stamms ausgegeben werden. Indem Sie den Namespace für jedes Element überschreiben und durch die leere Zeichenfolge ersetzen, haben Sie die Namespaces aus der Ausgabe entfernt.
Angenommen, dies ist der Typ:
So würden Sie so etwas während der Serialisierung verwenden:
Der XmlTextWriter ist allerdings irgendwie kaputt. Laut Referenzdokument wird beim Schreiben nicht Folgendes überprüft:
Diese Probleme mit XmlTextWriter gibt es seit Version 1.1 von .NET Framework und werden aus Gründen der Abwärtskompatibilität bestehen bleiben. Wenn Sie keine Bedenken bezüglich dieser Probleme haben, verwenden Sie auf jeden Fall den XmlTextWriter. Aber die meisten Leute wünschen sich etwas mehr Zuverlässigkeit.
Um dies zu erreichen, definieren Sie eine konkrete Implementierung des abstrakten XmlWriter und seiner 24 Methoden , während Sie Namespaces während der Serialisierung unterdrücken, anstatt von XmlTextWriter abzuleiten .
Ein Beispiel ist hier:
Geben Sie dann eine abgeleitete Klasse an, die die StartElement-Methode wie zuvor überschreibt:
Und dann benutze diesen Schreiber so:
Gutschrift dafür an Oleg Tkachenko .
quelle
LookupPrefix(string ns)
um immer eine leere Zeichenfolge zurückzugeben, um alle Schemadeklarationen zu entfernen.XmlWriter
undXmlWriterSettings
.Nachdem ich die Dokumentation von Microsoft und verschiedene Lösungen online gelesen habe, habe ich die Lösung für dieses Problem gefunden. Es funktioniert sowohl mit der integrierten
XmlSerializer
als auch mit der benutzerdefinierten XML-Serialisierung überIXmlSerialiazble
.Ich werde also dasselbe
MyTypeWithNamespaces
XML-Beispiel verwenden, das bisher in den Antworten auf diese Frage verwendet wurde.Das ist alles für diese Klasse. Nun hatten einige Einwände dagegen,
XmlSerializerNamespaces
irgendwo in ihren Klassen ein Objekt zu haben; Aber wie Sie sehen, habe ich es ordentlich in den Standardkonstruktor gesteckt und eine öffentliche Eigenschaft verfügbar gemacht, um die Namespaces zurückzugeben.Wenn es Zeit ist, die Klasse zu serialisieren, verwenden Sie den folgenden Code:
Sobald Sie dies getan haben, sollten Sie die folgende Ausgabe erhalten:
Ich habe diese Methode kürzlich in einem Projekt mit einer tiefen Hierarchie von Klassen erfolgreich verwendet, die für Webdienstaufrufe in XML serialisiert werden. In der Dokumentation von Microsoft ist nicht klar, was mit dem öffentlich zugänglichen
XmlSerializerNamespaces
Mitglied zu tun ist, wenn Sie es erstellt haben, und so viele halten es für nutzlos. Wenn Sie jedoch der Dokumentation folgen und sie auf die oben gezeigte Weise verwenden, können Sie anpassen, wie der XmlSerializer XML für Ihre Klassen generiert, ohne auf nicht unterstütztes Verhalten zurückgreifen oder Ihre eigene Serialisierung durch Implementierung "rollen" zu lassenIXmlSerializable
.Ich hoffe, dass diese Antwort ein für alle Mal zum Erliegen kommt, wie der Standard
xsi
und diexsd
Namespaces, die von derXmlSerializer
.UPDATE: Ich möchte nur sicherstellen, dass ich die Frage des OP zum Entfernen aller Namespaces beantwortet habe. Mein Code oben wird dafür funktionieren; lass mich dir zeigen wie. Im obigen Beispiel können Sie wirklich nicht alle Namespaces entfernen (da zwei Namespaces verwendet werden). Irgendwo in Ihrem XML-Dokument benötigen Sie so etwas wie
xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo
. Wenn die Klasse im Beispiel Teil eines größeren Dokuments ist, muss irgendwo über einem Namespace für eines von (oder für beide)Abracadbra
und deklariert werdenWhoohoo
. Wenn nicht, muss das Element in einem oder beiden Namespaces mit einem Präfix versehen sein (Sie können nicht zwei Standard-Namespaces haben, oder?). In diesem BeispielAbracadabra
handelt es sich also um den Defalt-Namespace. Ich könnte in meinerMyTypeWithNamespaces
Klasse ein Namespace-Präfix für denWhoohoo
Namespace wie folgt hinzufügen :In meiner Klassendefinition habe ich nun angegeben, dass sich das
<Label/>
Element im Namespace befindet"urn:Whoohoo"
, sodass ich nichts weiter tun muss. Wenn ich jetzt die Klasse mit meinem obigen Serialisierungscode unverändert serialisiere, ist dies die Ausgabe:Da
<Label>
es sich in einem anderen Namespace als der Rest des Dokuments befindet, muss es in gewisser Weise mit einem Namespace "dekoriert" werden. Beachten Sie, dass es noch keine sindxsi
undxsd
Namensräume.quelle
XmlWriter
ist, was in dem enthalten ist, das dieXmlMediaTypeFormatter
Namespaces xsi und xsd unabhängig davon in meine Ausgabe zwingt. Dies betrifft nur diejenigen, die die Standardeinstellungen von WebApi verwendenXmlMediaTypeFormatter
. Ich habe den Quellcode dafür kopiert und ihn so geändert, dass meine Namespaces-Eigenschaft an die Serialize-Methode übergeben wird, um zu verhindern, dassXmlWriter
die beiden Standardeinstellungen automatisch hinzugefügt werden. Siehe diese AntwortXmlSerializerNamespaces
, das mit dem dekoriert istXmlNamespacesDeclarationAttribute
. Dies wurde direkt von MSDN übernommen und verwendet im Wesentlichen die deklarierten Namespaces anstelle der von derXmlSerializer
.Dies ist die erste meiner beiden Antworten auf die Frage.
Wenn Sie die Namespaces genau steuern möchten, z. B. wenn Sie einige davon weglassen möchten, andere jedoch nicht, oder wenn Sie einen Namespace durch einen anderen ersetzen möchten, können Sie dies mit XmlAttributeOverrides tun .
Angenommen, Sie haben diese Typdefinition:
Und dieser Serialisierungs-Pseudocode:
Sie würden so etwas wie XML erhalten:
Beachten Sie, dass das Stammelement einen Standard-Namespace und das Element "Label" einen eindeutigen Namespace enthält. Diese Namespaces wurden durch die Attribute bestimmt, die den Typ im obigen Code schmücken.
Das XML-Serialisierungsframework in .NET bietet die Möglichkeit, die Attribute, die den eigentlichen Code schmücken , explizit zu überschreiben . Sie tun dies mit der XmlAttributesOverrides-Klasse und Freunden. Angenommen, ich habe denselben Typ und serialisiere ihn folgendermaßen:
Das Ergebnis sieht so aus;
Sie haben die Namespaces entfernt.
Eine logische Frage ist, ob Sie während der Serialisierung alle Namespaces von beliebigen Typen entfernen können, ohne die expliziten Überschreibungen zu durchlaufen. Die Antwort ist JA, und wie es geht, ist in meiner nächsten Antwort.
quelle
quelle