2016-10-10 12 views
0

Я работаю в C#, Visual Studio 2015, с таргетингом на .NET 4.5. У нас есть существующие системы (некоторые из них написаны на Java, некоторые устаревшие коды на C++ и т. Д.), Которые уже обмениваются XML в определенных форматах. Я изучил XMLSerializer, DataContractSerializer и кратко посмотрел на интерфейс ISerializable. Хотя я думаю, что я уже знаю ответ (ISerializable), я решил, что я увижу, есть ли у кого-нибудь умные идеи или решения для дублирования XML-формата, который нам нужен, без кодирования всех нас самих. У нас есть четыре различных сообщений XML, чтобы дублировать, вот только один из них:Простейший способ дублирования существующего формата XML в 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> 

Если кто-нибудь может подсказать блестящие ярлыки, по сравнению с очевидным решением, мы будем вечно благодарны.

Заранее спасибо.

+1

Если work_request_20.dtd является реальным, а не только грузом, вы можете сгенерировать xsd из dtd, а затем классы из xsd. – Will

+0

'ISerializable' не является ответом. «IXmlSerializable» может быть ответом, хотя и требующим максимальной работы. Пробовали ли вы генерировать классы C# с помощью [xsd.exe] (https://msdn.microsoft.com/en-us/library/x6c1kb0s.aspx) или загрузите их на http://xmltocsharp.azurewebsites.net/, а затем выполните сериализацию с 'XmlSerializer'? Это было бы намного проще. – dbc

+0

Кстати, в вашем XML отсутствует закрывающий тег ''. Могу ли я предположить, что это опечатка? – dbc

ответ

1

Сериализация с XmlSerializer, вероятно, будет самым простым решением. Если классы, созданные автоматически xsd.exe, слишком раздуты, вы можете использовать другой инструмент генерации кода, такой как http://xmltocsharp.azurewebsites.net/, чтобы сгенерировать их для вас - или даже сделать это самостоятельно вручную.

Например, я создал следующие типы с помощью http://xmltocsharp.azurewebsites.net/ затем сделал несколько ручных настроек, которые упоминаются в комментариях:

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

Используя эти типы, теперь я могу десериализации и повторно сериализации XML в Message<WorkRequestBody> и полученный повторно сериализованный XML эквивалентен исходному XML, согласно XNode.DeepEquals(). Образец fiddle.

Чтобы включить <!DOCTYPE ...> в переработанный XML-код, см. this question.

Реализация IXmlSerializable для корневого объекта примерно такая же сложность, как ручное чтение и запись всего графа объекта с помощью XmlReader и XmlWriter. Это, безусловно, возможно, но потребует больше работы, используя XmlSerializer. Вам все равно придется создавать POCOs для хранения данных в памяти, поэтому будет проще использовать сериализатор для автоматического чтения и записи этих POCO по мере возможности. См. here для получения справки о том, как это сделать правильно.

Чтение и письмо с LINQ to XML будет представлять собой промежуточный уровень сложности.

И, наконец, DataContractSerializer не подходит, поскольку нет возможности указать, что некоторые свойства C# должны быть сериализованы как атрибуты XML (source).

 Смежные вопросы

  • Нет связанных вопросов^_^