繁体   English   中英

将xml反序列化为基类的继承类

[英]deserialize xml into inherited classes from base class

我具有以下xml结构:

<Root1>
    <name>Name1</name>
    <company>Comp1</company>
    <url>site.com</url>
    <elements>
        <element id="12" type="1">
            <url>site1.com</url>
            <price>15000</price>
            ...
            <manufacturer_warranty>true</manufacturer_warranty>
            <country_of_origin>Япония</country_of_origin>
        </element>
        <element id="13" type="2">
            <url>site2.com</url>
            <price>100</price>
            ...
            <language>lg</language>
            <binding>123</binding>
        </element>
    </elements>
</Root1>

我需要将此xml反序列化为一个对象。 您可以看到该元素包含一些equals字段: urlprice 我想将这些字段移到父类中,然后从其他类继承该类。

我创建了类Root1

namespace app1
{
    [Serializable]
    public class Root1
    {
        [XmlElement("name")] 
        public string Name { get; set; }

        [XmlElement("company")] 
        public string Company { get; set; }

        [XmlElement("url")] 
        public string Url { get; set; }

        [XmlElement("elements")]
        public List<Element> ElementList { get; set; }
    }
}

然后我为Element创建了基类:

[Serializable]
    public class Element
    {
        [XmlElement("url")] 
        public string Url { get; set; }

        [XmlElement("price")] 
        public string Price { get; set; }
    }

然后我从其他类继承了这个类:

[Serializable]
public class Element1 : Element
{
    [XmlElement("manufacturer_warranty")] 
    public string mw { get; set; }

    [XmlElement("country_of_origin")] 
    public string co { get; set; }
}

[Serializable]
public class Element2 : Element
{
    [XmlElement("language")] 
    public string lg { get; set; }

    [XmlElement("binding")] 
    public string bind { get; set; }
}

当我将此xml反序列化为对象Root1我得到了对象-可以。 但是Elements列表仅包含Element对象,而不包含Element1Element2对象。

我如何反序列化此xml,以便Elements列表包含Element1Element2对象?

我认为您应该像这样使用XmlIncludeAttribute

[XmlInclude(typeof(Element1))]
public class Element
{
}

这是xml和代码。 我喜欢先使用测试数据进行序列化,然后反序列化。

<?xml version="1.0" encoding="utf-8"?>
<Root1>
  <name>Name1</name>
  <company>Comp1</company>
  <url>site.com</url>
  <element d2p1:type="Element1" xmlns:d2p1="http://www.w3.org/2001/XMLSchema-instance">
    <url>site1.com</url>
    <price>15000</price>
    <manufacturer_warranty>true</manufacturer_warranty>
    <country_of_origin>Япония</country_of_origin>
  </element>
  <element d2p1:type="Element2" xmlns:d2p1="http://www.w3.org/2001/XMLSchema-instance">
    <url>site2.com</url>
    <price>100</price>
    <language>lg</language>
    <binding>123</binding>
  </element>
</Root1>

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


namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string FILENAME = @"c:\temp\test.xml";
            Root1 root1 = new Root1() {
                Name = "Name1",
                Company = "Comp1",
                Url = "site.com",
                ElementList = new List<Element>() {
                    new Element1() {
                        Url = "site1.com",
                        Price = "15000",
                        mw = "true",
                        co = "Япония"
                    },
                    new Element2() {
                        Url = "site2.com",
                        Price = "100",
                        lg = "lg",
                        bind = "123"
                    }
                }
            };

            XmlSerializer serializer = new XmlSerializer(typeof(Root1));
            StreamWriter writer = new StreamWriter(FILENAME);
            XmlSerializerNamespaces _ns = new XmlSerializerNamespaces();
            _ns.Add("", "");
            serializer.Serialize(writer, root1, _ns);
            writer.Flush();
            writer.Close();
            writer.Dispose();

            XmlSerializer xs = new XmlSerializer(typeof(Root1));
            XmlTextReader reader = new XmlTextReader(FILENAME);
            Root1 newRoot1 = (Root1)xs.Deserialize(reader);


        }

    }
    [XmlRoot("Root1")]
    public class Root1
    {
        [XmlElement("name")]
        public string Name { get; set; }

        [XmlElement("company")]
        public string Company { get; set; }

        [XmlElement("url")]
        public string Url { get; set; }

        [XmlElement("element")]
        public List<Element> ElementList { get; set; }
    }
    [XmlInclude(typeof(Element1))]
    [XmlInclude(typeof(Element2))]
    [XmlRoot("element")]
    public class Element
    {
        [XmlElement("url")]
        public string Url { get; set; }

        [XmlElement("price")]
        public string Price { get; set; }
    }
    [XmlRoot("element1")]
    public class Element1 : Element
    {
        [XmlElement("manufacturer_warranty")]
        public string mw { get; set; }

        [XmlElement("country_of_origin")]
        public string co { get; set; }
    }

    [XmlRoot("element2")]
    public class Element2 : Element
    {
        [XmlElement("language")]
        public string lg { get; set; }

        [XmlElement("binding")]
        public string bind { get; set; }
    }



}

下面的代码与您发布的XML更好地匹配。 您需要将生成的xml与xml进行比较。

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


namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string FILENAME = @"c:\temp\test.xml";
            Root1 root1 = new Root1()
            {
                Name = "Name1",
                Company = "Comp1",
                Url = "site.com",
                cElement = new Elements() { 
                   ElementList = new List<Element>() {
                       new Element1() {
                           Url = "site1.com",
                           Price = "15000",
                           mw = "true",
                           co = "Япония"
                       },
                       new Element2() {
                           Url = "site2.com",
                           Price = "100",
                           lg = "lg",
                           bind = "123"
                       }
                    }

                }
            };

            XmlSerializer serializer = new XmlSerializer(typeof(Root1));
            StreamWriter writer = new StreamWriter(FILENAME);
            XmlSerializerNamespaces _ns = new XmlSerializerNamespaces();
            _ns.Add("", "");
            serializer.Serialize(writer, root1, _ns);
            writer.Flush();
            writer.Close();
            writer.Dispose();

            XmlSerializer xs = new XmlSerializer(typeof(Root1));
            XmlTextReader reader = new XmlTextReader(FILENAME);
            Root1 newRoot1 = (Root1)xs.Deserialize(reader);

        }

    }
    [XmlRoot("Root1")]
    public class Root1
    {
        [XmlElement("name")]
        public string Name { get; set; }

        [XmlElement("company")]
        public string Company { get; set; }

        [XmlElement("url")]
        public string Url { get; set; }

        [XmlElement("elements")]
        public Elements cElement { get; set; }
    }

    [XmlRoot("elements")]
    public class Elements
    {
        [XmlElement("element")]
        public List<Element> ElementList { get; set; }
    }

    [XmlInclude(typeof(Element1))]
    [XmlInclude(typeof(Element2))]
    [XmlRoot("element", Namespace = "")]
    public class Element
    {
        [XmlElement("url")]
        public string Url { get; set; }

        [XmlElement("price")]
        public string Price { get; set; }
    }
    [XmlRoot("element1", Namespace = "")]
    public class Element1 : Element
    {
        [XmlElement("manufacturer_warranty")]
        public string mw { get; set; }

        [XmlElement("country_of_origin")]
        public string co { get; set; }
    }

    [XmlRoot("element2", Namespace = "")]
    public class Element2 : Element
    {
        [XmlElement("language")]
        public string lg { get; set; }

        [XmlElement("binding")]
        public string bind { get; set; }
    }

}​

@netwer对您不起作用,因为上面建议的代码生成的xml(以下)与用于反序列化的xml不匹配(请参阅如何在element中指定派生类型)。

<?xml version="1.0" encoding="utf-8"?>
<Root1>
  <name>Name1</name>
  <company>Comp1</company>
  <url>site.com</url>
  <elements>
    <element d3p1:type="Element1" xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance">
      <url>site1.com</url>
      <price>15000</price>
      <manufacturer_warranty>true</manufacturer_warranty>
      <country_of_origin>Япония</country_of_origin>
    </element>
    <element d3p1:type="Element2" xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance">
      <url>site2.com</url>
      <price>100</price>
      <language>lg</language>
      <binding>123</binding>
    </element>
  </elements>
</Root1>

因此,您将不得不将此格式与源xml(更改代码或返回此xml数据的API)进行匹配,或者采用另一种方法。 即使您设法处理前一个属性,也必须找到一种访问Element1或Element2特定属性的方法。

newRoot1.Elements.ElementList [i]将始终只允许您访问价格和网址,因为您的列表属于Element类型。 尽管ElementList [i]的运行时类型为Element1或Element2,但是如何检测到呢?

在这里,我建议替代方法。 无论您的应用程序(客户端)是生成此xml还是在命中API时将其返回的服务器,您都应该能够收集适用于“元素”对象的所有字段的信息。 如果它是您的代码,您已经知道了;如果它是API,则必须有一个文档。 这样,您只需创建一个“元素”(没有派生类)并进行适当的检查(主要是string.IsNullOrEmpty()),然后再访问代码中的元素类属性值即可。 只有在xml'element'元素中存在的属性才会被视为剩余,该实例的属性将设置为NULL。

[Serializable]
public class Element
{
   [XmlElement("url")]
   public string Url { get; set; }

   [XmlElement("price")] 
   public string Price { get; set; }

   [XmlElement("manufacturer_warranty")]
   public string mw { get; set; }

   [XmlElement("country_of_origin")]
   public string co { get; set; }

   [XmlElement("language")]
   public string lg { get; set; }

   [XmlElement("binding")]
   public string bind { get; set; }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM