2016-10-10 2 views
0

zu duplizieren Ich arbeite in C#, Visual Studio 2015, Targeting .NET 4.5. Wir haben bestehende Systeme (einige in Java geschrieben, einige Legacy-Code in C++, etc.), die bereits XML in bestimmten Formaten austauschen. Ich habe XMLSerializer, DataContractSerializer untersucht und kurz die ISerializable-Schnittstelle betrachtet. Obwohl ich denke, dass ich die Antwort bereits kenne (ISerializable), dachte ich, ich würde sehen, ob jemand clevere Ideen oder Lösungen für das Duplizieren des XML-Formats hat, das wir brauchen, ohne alles selbst zu programmieren. Wir haben vier verschiedene XML-Nachrichten zu duplizieren, hier ist nur einer von ihnen:Einfachste Möglichkeit, ein bereits bestehendes XML-Format in C#

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE message SYSTEM "work_request_20.dtd"> 
<message message_id="1005" message_dt="01/21/2008 09:50:23.221 AM" message_type="Work_Request" message_sub_type="New" message_dtd_version_number="2.0"> 
<header> 
    <from_application_id>3367e115-c873-4ac9-a1dd-7e45231dc3d5</from_application_id> 
    <to_application_id>35e0cca2-e423-4ffe-ba07-7d056775c228</to_application_id> 
</header> 
<body> 
    <work_request requisition_number="REQ44"> 
     <client client_id="44"> 
       <first_name>Barak</first_name> 
       <last_name>Obama</last_name> 
     </client> 
     <patient patient_id="4444" patient_species="CANINE" patient_gender="MALE_INTACT"> 
      <patient_name>Bo</patient_name> 
       <patient_breed>Portuguese Water Dog</patient_breed> 
       <patient_birth_dt>04/04/2004</patient_birth_dt> 
       <patient_weight patient_weight_uom="lbs"> 
        <weight>44.4</weight> 
       </patient_weight> 
     </patient> 
     <doctor> 
      <first_name>Surgeon</first_name> 
      <last_name>General</last_name> 
     </doctor>  
     <service_add> 
      <service_cd>ALB</service_cd> 
      <service_cd>GLU</service_cd> 
      <service_cd>BUN</service_cd> 
     </service_add> 
    </work_request> 
</body> 
</message> 

Wenn jemand eine brillanten Verknüpfungen auf die offensichtliche Lösung im Vergleich vorschlagen kann, würden wir immer dankbar sein.

Vielen Dank im Voraus.

+1

Wenn work_request_20.dtd real ist und nicht nur Cargo-Kultivierung, können Sie ein xsd aus dem dtd und dann Klassen aus dem xsd generieren. – Will

+0

'ISerializable' ist nicht die Antwort. 'IXmlSerializable' könnte eine Antwort sein, wenn auch eine, die maximale Arbeit erfordert. Haben Sie versucht, C# -Klassen mit [xsd.exe] (https://msdn.microsoft.com/en-us/library/x6c1kb0s.aspx) oder durch Hochladen auf http://xmltocsharp.azurewebsites.net/ und anschließendes Serialisieren zu erstellen mit 'XmlSerializer'? Das wäre viel einfacher. – dbc

+0

Übrigens fehlt in Ihrem XML ein schließendes Tag ''. Darf ich annehmen, dass das ein Tippfehler ist? – dbc

Antwort

1

Serialisierung mit XmlSerializer wird wahrscheinlich die einfachste Lösung sein. Wenn Klassen, die von xsd.exe automatisch generiert wurden, zu aufgebläht sind, können Sie sie mit einem anderen Codegenerierungsprogramm wie http://xmltocsharp.azurewebsites.net/ für Sie erstellen - oder sogar manuell.

Zum Beispiel erzeugen ich die folgenden Typen mit http://xmltocsharp.azurewebsites.net/ dann ein paar manuellen Optimierungen vorgenommen, die in den Kommentaren erwähnt werden:

[XmlRoot(ElementName="header")] 
public class Header { 

    // I modified the types of these properties from string to Guid 
    [XmlElement(ElementName="from_application_id")] 
    public Guid From_application_id { get; set; } 
    [XmlElement(ElementName="to_application_id")] 
    public Guid To_application_id { get; set; } 

} 

[XmlRoot(ElementName="client")] 
public class Client { 
    [XmlElement(ElementName="first_name")] 
    public string First_name { get; set; } 
    [XmlElement(ElementName="last_name")] 
    public string Last_name { get; set; } 
    [XmlAttribute(AttributeName="client_id")] 
    public string Client_id { get; set; } 
} 

[XmlRoot(ElementName="patient_weight")] 
public class Patient_weight { 
    // I changed weight from string to decimal 
    [XmlElement(ElementName="weight")] 
    public decimal Weight { get; set; } 
    [XmlAttribute(AttributeName="patient_weight_uom")] 
    public string Patient_weight_uom { get; set; } 
} 

[XmlRoot(ElementName="patient")] 
public class Patient { 
    [XmlElement(ElementName="patient_name")] 
    public string Patient_name { get; set; } 
    [XmlElement(ElementName="patient_breed")] 
    public string Patient_breed { get; set; } 
    [XmlElement(ElementName="patient_birth_dt")] 
    public string Patient_birth_dt { get; set; } 
    [XmlElement(ElementName="patient_weight")] 
    public Patient_weight Patient_weight { get; set; } 
    [XmlAttribute(AttributeName="patient_id")] 
    public string Patient_id { get; set; } 
    [XmlAttribute(AttributeName="patient_species")] 
    public string Patient_species { get; set; } 
    [XmlAttribute(AttributeName="patient_gender")] 
    public string Patient_gender { get; set; } 
} 

[XmlRoot(ElementName="doctor")] 
public class Doctor { 
    [XmlElement(ElementName="first_name")] 
    public string First_name { get; set; } 
    [XmlElement(ElementName="last_name")] 
    public string Last_name { get; set; } 
} 

[XmlRoot(ElementName="work_request")] 
public class Work_request { 
    [XmlElement(ElementName="client")] 
    public Client Client { get; set; } 
    [XmlElement(ElementName="patient")] 
    public Patient Patient { get; set; } 
    [XmlElement(ElementName="doctor")] 
    public Doctor Doctor { get; set; } 

    // I simplied this into a list of strings. 
    [XmlArray(ElementName="service_add")] 
    [XmlArrayItem("service_cd")] 
    public List<string> Service_add { get; set; } 

    [XmlAttribute(AttributeName="requisition_number")] 
    public string Requisition_number { get; set; } 
} 

[XmlRoot(ElementName="body")] 
// I renamed this to WorkRequestBody 
public class WorkRequestBody 
{ 
    [XmlElement(ElementName="work_request")] 
    public Work_request Work_request { get; set; } 
} 

[XmlRoot(ElementName="message")] 
// I made this generic to account for multiple types of messge. 
public class Message<T> where T : class, new() 
{ 
    [XmlElement(ElementName="header")] 
    public Header Header { get; set; } 
    [XmlElement(ElementName="body")] 
    public T Body { get; set; } 
    [XmlAttribute(AttributeName="message_id")] 
    public string Message_id { get; set; } 
    [XmlAttribute(AttributeName="message_dt")] 
    public string Message_dt { get; set; } 
    [XmlAttribute(AttributeName="message_type")] 
    public string Message_type { get; set; } 
    [XmlAttribute(AttributeName="message_sub_type")] 
    public string Message_sub_type { get; set; } 
    [XmlAttribute(AttributeName="message_dtd_version_number")] 
    public string Message_dtd_version_number { get; set; } 
} 

diese Typen verwenden, kann ich jetzt deserialisieren und erneut serialisiert Ihre XML-Daten in ein Message<WorkRequestBody> und das resultierende re-serialisierte XML entspricht dem ursprünglichen XML gemäß . Probe fiddle.

Um eine <!DOCTYPE ...> in die re-serialisierte XML einzuschließen, siehe this question.

Das Implementieren von IXmlSerializable für das Stammobjekt ist ungefähr die gleiche Schwierigkeit wie das manuelle Lesen und Schreiben Ihres gesamten Objektdiagramms mit XmlReader und XmlWriter. Es ist sicherlich möglich, erfordert aber mehr Arbeit mit XmlSerializer. Sie müssen weiterhin POCOs entwerfen, um die Daten im Speicher zu halten. Daher ist es einfacher, einen Serializer zu verwenden, um diese POCOs automatisch zu lesen und zu schreiben, wann immer dies möglich ist. Eine Anleitung zur korrekten Vorgehensweise finden Sie unter here.

Lesen und Schreiben mit LINQ to XML würde einen mittleren Schwierigkeitsgrad darstellen.

Schließlich ist DataContractSerializer nicht geeignet, da es keine Möglichkeit gibt, anzugeben, dass bestimmte C# -Eigenschaften als XML-Attribute serialisiert werden sollten (source).

Verwandte Themen