按属性值获取xml节点并反序列化该节点

时间:2015-06-10 05:04:50

标签: c# xml xml-declaration

我有两个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创建了Mapping Class,如下所示:

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");
            }
        }        
}

我想仅希望将格式2中具有Type="Print"的单个节点的XML转换为Template类。有没有通用的方法可以将XML文件(Foarmat 1和格式2的单个节点)反序列化为Template类?

1 个答案:

答案 0 :(得分:0)

是的,可以将Linq to XMLXmlSerializer

合并来完成
  1. 将XML加载到XDocument

  2. 使用linq在XML元素层次结构中查找具有适当属性的适当元素。

  3. 反序列化所选元素,使用XElement.CreateReader()传递一个XmlReader,将元素及其后代读取到序列化程序。

  4. 因此,例如:

        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");
            }
        }
    }