2017-03-22 5 views
0

Ich bemerkte, dass mein XML nach der Serialisierung ändert. z.B.
* die ns in dem Start des Message Element
* xmlns:ns Attribut verschwindet wird xmlns
* gibt es neue Attribute im Message-Element hinzugefügt - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" und xmlns:xsd="http://www.w3.org/2001/XMLSchema"
* neues Attribut in Header Element - xmlnsXML ändert sich nach Serialisierung

Wie Kann ich die ursprüngliche Form des XML beibehalten und verhindern, dass diese Attribute hinzugefügt werden?

Hier ist, wie die ursprüngliche XML wie folgt aussieht:

<?xml version="1.0" encoding="UTF-8"?> 
<ns:Message xmlns:ns="http://example.com"> 
    <Header version="1.0"> 
    <Sender>3015207400109</Sender> 
    <Receiver>8711200999903</Receiver> 
    <MessageID>000D2613F64AC021ED783C084735EC78E53</MessageID> 
    <CreationDateTime>2017-03-21T08:00:47Z</CreationDateTime> 
    </Header> 
</ns:Message> 

Und hier ist der xml, nachdem es serialisiert wurde:

<?xml version="1.0" encoding="UTF-8"?> 
<Message xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://example.com"> 
    <Header version="1.0" xmlns=""> 
    <Sender>3015207400109</Sender> 
    <Receiver>8711200999903</Receiver> 
    <MessageID>000D2613F64AC021ED783C084735EC78E53</MessageID> 
    <CreationDateTime>2017-03-21T08:00:47Z</CreationDateTime> 
    </Header> 
</Message> 

Der Code unten ist die (generiert) Klasse, die die Message xml darstellt .

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://example.com")] 
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://example.com", IsNullable = false)] 
public partial class Message 
{ 

    private Header headerField; 

    /// <remarks/> 
    [System.Xml.Serialization.XmlElementAttribute(Namespace = "")] 
    public Header Header 
    { 
     get 
     { 
      return this.headerField; 
     } 
     set 
     { 
      this.headerField = value; 
     } 
    } 
} 

/// <remarks/> 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] 
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)] 
public partial class Header 
{ 

    private ulong senderField; 

    private ulong receiverField; 

    private string messageIDField; 

    private System.DateTime creationDateTimeField; 

    private decimal versionField; 

    /// <remarks/> 
    public ulong Sender 
    { 
     get 
     { 
      return this.senderField; 
     } 
     set 
     { 
      this.senderField = value; 
     } 
    } 

    /// <remarks/> 
    public ulong Receiver 
    { 
     get 
     { 
      return this.receiverField; 
     } 
     set 
     { 
      this.receiverField = value; 
     } 
    } 

    /// <remarks/> 
    public string MessageID 
    { 
     get 
     { 
      return this.messageIDField; 
     } 
     set 
     { 
      this.messageIDField = value; 
     } 
    } 

    /// <remarks/> 
    public System.DateTime CreationDateTime 
    { 
     get 
     { 
      return this.creationDateTimeField; 
     } 
     set 
     { 
      this.creationDateTimeField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public decimal version 
    { 
     get 
     { 
      return this.versionField; 
     } 
     set 
     { 
      this.versionField = value; 
     } 
    } 
} 
+1

Beide XML-Dokumente sind semantisch gleich. Ist der Unterschied für Sie ein Problem? Wenn ja, was ist das? – JLRishe

Antwort

1

Die beiden XML-Dateien, die Sie anzeigen, sind semantisch identisch. Daher würde ich empfehlen, sich keine Gedanken über die Tatsache zu machen, dass XmlSerializer XML-Standardnamespaces einfügt oder ein anderes Präfixschema als in der ursprünglichen Datei verwendet.

Wenn aus welchem ​​Grund auch immer, Sie müssen Unterdrückungs-Ausgabe der Standard-Namespaces und muss die Vorfixierung Schema der ursprünglichen Datei erhalten, ist hier, was Sie tun können.

Zum einen die xsi und xsd Namensräume auf der Stammebene zu verzichten, folgen Sie den Anweisungen von Omitting all xsi and xsd namespaces when serializing an object in .NET?:

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

Als nächstes müssen Sie die ursprüngliche Form des xml halten um zuerst Irgendwie erfassen sie die tatsächlichen XML-Namespaces und -Präfixe, die beim Lesen der Datei gefunden wurden, und speichern sie in der Klasse Message irgendwo zur späteren Wiederverwendung. Glücklicherweise unterstützt XmlSerializer dies: Sie können eine XmlSerializerNamespaces geschätzte öffentliche Eigenschaft oder ein öffentliches Feld zu Message hinzufügen und mit [XmlNamespaceDeclarations] markieren. Dieses Member erfasst jetzt Namespaces, die während der Deserialisierung festgestellt werden, und bewirkt, dass diese Namespaces während der Serialisierung hinzugefügt werden.

Setzt man diese beiden Ideen zusammen, können Sie Ihre Message Typ wie folgt ändern:

public partial class Message 
{ 
    [XmlNamespaceDeclarations] 
    public XmlSerializerNamespaces XmlFileNamespaces { get; set; } 

    /// <summary> 
    /// returns a XmlSerializerNamespaces to use when serializing a Message as the root XML object. 
    /// If Message was previously deserialized from XML, the actual namespaces observed will be returned. 
    /// Otherwise, a default will be returned that suppresses output of the xmlns:xsi and xmlns:xsd namespace attributes. 
    /// </summary> 
    [XmlIgnore] 
    public XmlSerializerNamespaces XmlRootNamespaces 
    { 
     get 
     { 
      if (XmlFileNamespaces != null) 
       return XmlFileNamespaces; 
      var xmlNamespaces = new XmlSerializerNamespaces(); 
      xmlNamespaces.Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines. 
      // xmlNamespaces.Add("ns", "http://example.com"); // Or, if you prefer, add this namespace as well as disabling xmlns:xsi and xmlns:xsd. 
      return xmlNamespaces; 
     } 
    } 
} 

Und von und nach XML serialisiert wie folgt:

var message = xml.LoadFromXml<Message>(); 

var reserializedXml = message.GetXml(message.XmlRootNamespaces); 

folgende Erweiterungsmethoden verwenden:

public static class XmlSerializationHelper 
{ 
    public static T LoadFromXml<T>(this string xmlString) 
    { 
     using (StringReader reader = new StringReader(xmlString)) 
     { 
      return (T)new XmlSerializer(typeof(T)).Deserialize(reader); 
     } 
    } 

    public static string GetXml<T>(this T obj, XmlSerializerNamespaces ns) 
    { 
     using (var textWriter = new Utf8StringWriter()) 
     { 
      var settings = new XmlWriterSettings() { Indent = true }; // For cosmetic purposes. 
      using (var xmlWriter = XmlWriter.Create(textWriter, settings)) 
       new XmlSerializer(obj.GetType()).Serialize(xmlWriter, obj, ns); 
      return textWriter.ToString(); 
     } 
    } 
} 

// http://stackoverflow.com/questions/3862063/serializing-an-object-as-utf-8-xml-in-net 
public class Utf8StringWriter : StringWriter 
{ 
    public override Encoding Encoding 
    { 
     get { return Encoding.UTF8; } 
    } 
} 

Prototyp fiddle.

+0

das funktioniert für mich. Gracias! :) – yonan2236