2015-06-10 4 views
1

У меня есть два XML-файла, как показано нижеПолучить XML-узел по значению атрибута и десериализации этот узел

Формат 1:

<Template Type="Print"> 
    <PrintWidth>7</PrintWidth> 
    <PrintHeight>5</PrintHeight> 
</Template> 

Формат 2:

<Templates> 
    <Template Type="Print"> 
    <PrintWidth>7</PrintWidth> 
    <PrintHeight>5</PrintHeight> 
    </Template> 
    <Template Type="Print"> 
    <PrintWidth>7</PrintWidth> 
    <PrintHeight>5</PrintHeight> 
    </Template> 
</Templates> 

Я создал Класс сопоставления для формата 1, как указано ниже:

public class Template 
{    
     private double _printWidth;   
     private double _printHeight;   

     /// <summary> 
     /// Print width in inches 
     /// </summary> 
     [System.Xml.Serialization.XmlAttributeAttribute()] 
     public double PrintWidth { 
      get { 
       return this._printWidth; 
      } 
      set { 
       this._printWidth = value; 
       this.RaisePropertyChanged("PrintWidth"); 
      } 
     }     

     [System.Xml.Serialization.XmlAttributeAttribute()] 
     public double PrintHeight { 
      get { 
       return this._printHeight; 
      } 
      set { 
       this._printHeight = value; 
       this.RaisePropertyChanged("PrintHeight"); 
      } 
     }   
} 

Я хотел запросить только один узел XML в формате 2, который имеет Type="Print" в класс Template. Есть ли общий способ, с помощью которого я могу десериализовать оба файла XML (Foarmat 1 и один узел формата 2) до класса Template?

ответ

0

Да, это может быть сделано путем объединения Linq to XML с XmlSerializer:

  1. нагрузки на XML в XDocument

  2. Использование LINQ, чтобы найти подходящий элемент с соответствующим атрибутом в иерархии XML-элементов ,

  3. Отключить выбранный элемент, используя XElement.CreateReader(), чтобы передать XmlReader, который считывает элемент и его потомков в сериализатор.

Так, например:

public static void Test() 
    { 
     string xml1 = @"<Template Type=""Print""> 
      <PrintWidth>7</PrintWidth> 
      <PrintHeight>5</PrintHeight> 
     </Template>"; 

     string xml2 = @"<Templates> 
      <Template Type=""Print""> 
      <PrintWidth>7</PrintWidth> 
      <PrintHeight>5</PrintHeight> 
      </Template> 
      <Template Type=""Print""> 
      <PrintWidth>7</PrintWidth> 
      <PrintHeight>5</PrintHeight> 
      </Template> 
     </Templates>"; 

     var template1 = ExtractTemplate(xml1); 

     var template2 = ExtractTemplate(xml2); 

     Debug.Assert(template1 != null && template2 != null 
      && template1.PrintWidth == template2.PrintWidth 
      && template1.PrintWidth == 7 
      && template1.PrintHeight == template2.PrintHeight 
      && template1.PrintHeight == 5); // No assert 
    } 

    public static Template ExtractTemplate(string xml) 
    { 
     // Load the XML into an XDocument 
     var doc = XDocument.Parse(xml); 

     // Find the first element named "Template" with attribute "Type" that has value "Print". 
     var element = doc.Descendants("Template").Where(e => e.Attributes("Type").Any(a => a.Value == "Print")).FirstOrDefault(); 

     // Deserialize it to the Template class 
     var template = (element == null ? null : element.Deserialize<Template>()); 

     return template; 
    } 

Использование метода расширения:

public static class XObjectExtensions 
{ 
    public static T Deserialize<T>(this XContainer element) 
    { 
     return element.Deserialize<T>(new XmlSerializer(typeof(T))); 
    } 

    public static T Deserialize<T>(this XContainer element, XmlSerializer serializer) 
    { 
     using (var reader = element.CreateReader()) 
     { 
      object result = serializer.Deserialize(reader); 
      if (result is T) 
       return (T)result; 
     } 
     return default(T); 
    } 
} 

Кстати, ваш Template класс имеет ошибку: нужно отметить PrintWidth и PrintHeight с [XmlElement], а чем [XmlAttribute], чтобы десериализовать этот XML правильно:

public class Template 
{ 
    private double _printWidth; 
    private double _printHeight; 

    /// <summary> 
    /// Print width in inches 
    /// </summary> 
    [System.Xml.Serialization.XmlElementAttribute()] 
    public double PrintWidth 
    { 
     get 
     { 
      return this._printWidth; 
     } 
     set 
     { 
      this._printWidth = value; 
      this.RaisePropertyChanged("PrintWidth"); 
     } 
    } 

    [System.Xml.Serialization.XmlElementAttribute()] 
    public double PrintHeight 
    { 
     get 
     { 
      return this._printHeight; 
     } 
     set 
     { 
      this._printHeight = value; 
      this.RaisePropertyChanged("PrintHeight"); 
     } 
    } 
} 
Смежные вопросы