[英]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字段: url
和price
。 我想将这些字段移到父类中,然后从其他类继承该类。
我创建了类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
对象,而不包含Element1
和Element2
对象。
我如何反序列化此xml,以便Elements
列表包含Element1
和Element2
对象?
我认为您应该像这样使用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.