2015-06-03 5 views
1

Как десериализации XML, как это:XML десериализации из атрибутов свойств

<query> 
    <parameters> 
    <param name="lastUpdate">2012-05-25</param> 
    <param name="code">11222122</param> 
    <param name="type">idnLookup</param> 
    </parameters> 
    <response> 
    <category name="person" version="1"> 
     <field name="surname">Soap</field> 
     <field name="name1">Joe</field> 
     <field name="date_of_birth">1973-05-09</field> 
    </category> 
    <category name="contact" version="1"> 
     <row> 
     <field name="phone">0118063433</field> 
     <field name="type">home</field> 
     <field name="date">2003-01-01</field> 
     </row> 
     <row> 
     <field name="phone">0124666566</field> 
     <field name="type">home</field> 
     <field name="date">2008-03-11</field> 
     </row> 
    </category> 
    </response> 
</query> 

в классовой структуре, как это:

public class Query{ 
public string lastUpdate {get;set;} 
public string code {get;set;} 
public string type {get;set;} 
public Response response {get;set;} 
} 
class Response{ 
    public Person person {get;set;} 
    public Contact[] contacts {get;set;} 
} 
class Person { 
    public string surname {get;set;} 
    public string name1 {get;set;} 
    public string date_of_birth {get;set;} 
} 
class Contact { 
    public string phone {get;set;} 
    public string type {get;set;} 
    public string date {get;set;} 
} 

используя стандартный .net XML сериалайзер. Или мне нужно катиться самостоятельно?

+1

Ввод слишком специфичен для стандартного сериализатора Xml, чтобы это можно было сделать. Я думаю, что вы могли бы запустить преобразование XSL до стандартной стандартной десериализации, но может быть проще скомпилировать пользовательский C# ... Вы также можете посмотреть интерфейс IXmlSerializable –

+0

@SimonMourier Я бы всегда советовал модель DTO (модель между моделью домена и сериализованной формой, которая соответствует уровню сериализации) до 'IXmlSerializable' - этот API * ужасный *, чтобы получить право. Мне нравится идея XSLT здесь. –

+1

В качестве побочного примечания: кто бы ни придумал этот макет xml ... не знает, как xml; p –

ответ

1

Для расширения XSLT идеи Саймона, рассмотрим следующий XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
    </xsl:template> 
    <xsl:template match="/query/parameters"> 
    <xsl:apply-templates select="*"/> 
    <!-- removes a level from the hierarchy by applying directly --> 
    </xsl:template> 
    <xsl:template match="*[@name]"> 
    <xsl:element name="{@name}"> 
     <xsl:apply-templates select="@*[name()!='name'] | * | text()"/> 
    </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

Ключевой матч здесь является *[@name], которая принимает что-либо вида:

<foo name="abc" ...>...</foo> 

и переписывает его как:

<abc ...>...</abc> 

Это превращает ваш XML в:

<query> 
    <lastUpdate>2012-05-25</lastUpdate> 
    <code>11222122</code> 
    <type>idnLookup</type> 
    <response> 
    <person version="1"> 
     <surname>Soap</surname> 
     <name1>Joe</name1> 
     <date_of_birth>1973-05-09</date_of_birth> 
    </person> 
    <contact version="1"> 
     <row> 
     <phone>0118063433</phone> 
     <type>home</type> 
     <date>2003-01-01</date> 
     </row> 
     <row> 
     <phone>0124666566</phone> 
     <type>home</type> 
     <date>2008-03-11</date> 
     </row> 
    </contact> 
    </response> 
</query> 

который может быть отображен на модели с очень незначительными твиков в качестве атрибутов:

[XmlRoot("query")] // <==== add this 
public class Query {...} 

[XmlArray("contact"), XmlArrayItem("row")] // <=== add this 
public Contact[] contacts { get; set; } 

который может быть использован, например:

static void Main() 
{ 
    XslCompiledTransform xslt = new XslCompiledTransform(); 
    xslt.Load("my.xslt"); 
    var sw = new StringWriter(); 
    xslt.Transform("my.xml", null, sw); 
    var transformedXml = sw.ToString(); 

    Console.WriteLine(transformedXml); 
    Query query; 
    using (var reader = XmlReader.Create(new StringReader(transformedXml))) 
    { 
     query = (Query)new XmlSerializer(typeof(Query)).Deserialize(reader); 
    } 
    // query is now fully populated 
} 
+0

Спасибо за это. Работает как шарм. и I + 1'd комментарий Саймона за предложение xslt –

0

Попробуйте

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml; 
using System.Xml.Serialization; 
using System.IO; 

namespace ConsoleApplication32 
{ 
    class Program 
    { 
     const string FILENAME = @"c:\temp\Test.xml"; 
     static void Main(string[] args) 
     { 
      XmlSerializer xs = new XmlSerializer(typeof(Query)); 
      XmlTextReader reader = new XmlTextReader(FILENAME); 
      Query query = (Query)xs.Deserialize(reader); 
      query.Response.GetContacts(); 

     } 
    } 
    [XmlRoot("query")] 
    public class Query 
    { 
     [XmlElement("parameters")] 
     public Parameters Parameters {get;set;} 
     [XmlElement("response")] 
     public Response Response {get;set;} 
    } 
    [XmlRoot("parameters")] 
    public class Parameters{ 
     private string lastUpdate {get;set;} 
     private string code {get;set;} 
     private string type {get;set;} 

     [XmlElement("param")] 
     public List<Param> m_params {get; set;} 

    } 
    [XmlRoot("param")] 
    public class Param 
    { 
     [XmlAttribute("name")] 
     public string name {get; set;} 
    } 

    [XmlRoot("response")] 
    public class Response 
    { 
     private Person person {get;set;} 
     private List<Contact> contacts = new List<Contact>(); 
     [XmlElement("category")] 
     public List<Category> categories {get;set;} 

     public void GetContacts() 
     { 
      foreach (Category category in categories) 
      { 
       string catName = category.name; 
       switch (catName) 
       { 
        case "person" : 
         person = new Person(); 
         foreach (Field field in category.fields) 
         { 
          switch (field.name) 
          { 
           case "surname" : 
            person.surname = field.value; 
            break; 
           case "name1": 
            person.name1 = field.value; 
            break; 
           case "date_of_birth": 
            person.date_of_birth = field.value; 
            break; 
           default : 
            break; 
          } 
         } 
         break; 
        case "contact" : 
         foreach (Row row in category.row) 
         { 
          Contact newContact = new Contact(); 
          contacts.Add(newContact); 

          foreach (Field field in row.fields) 
          { 
           switch (field.name) 
           { 
            case "phone": 
             newContact.phone = field.value; 
             break; 
            case "type": 
             newContact.type = field.value; 
             break; 
            case "date": 
             newContact.date = field.value; 
             break; 
            default: 
             break; 
           } 
          } 
         } 
         break; 
       } 
      } 
     } 
    } 
    [XmlRoot("category")] 
    public class Category 
    { 
     [XmlAttribute("name")] 
     public string name {get; set;} 
     [XmlAttribute("version")] 
     public string version { get; set; } 
     [XmlElement("field")] 
     public List<Field> fields {get; set;} 
     [XmlElement("row")] 
     public List<Row> row {get;set;} 
    } 
    [XmlRoot("row")] 
    public class Row 
    { 
     [XmlElement("field")] 
     public List<Field> fields {get; set;} 
    } 

    [XmlRoot("field")] 
    public class Field 
    { 
     [XmlAttribute("name")] 
     public string name { get; set; } 
     [XmlText] 
     public string value { get; set; } 
    } 

    class Person { 
     public string surname {get;set;} 
     public string name1 {get;set;} 
     public string date_of_birth {get;set;} 
    } 
    class Contact { 
     public string phone {get;set;} 
     public string type {get;set;} 
     public string date {get;set;} 
    } 
} 
Смежные вопросы