从一个 XML 文件反序列化两个单独的对象
Deserialize two separate objects from one XML file
我正在将两个对象序列化为 XML 并写入两个单独的 XML 文件,然后将这两个文件合并为一个文件。我想要做的是能够从合并文件中单独反序列化每个对象。
<?xml version="1.0" encoding="utf-8"?>
<root>
<ArrayOfMapItem>
<MapItem>
<EpgId xmlns="Company.Domain.Name.Space">0000DAC2-0000-0000-0000-000000000000</EpgId>
<MapId xmlns="Company.Domain.Name.Space">5D195A5B-FBBF-4042-8AB3-E4558CA1D347</MapId>
<ServiceCollectionId xmlns="Company.Domain.Name.Space">657A62F8-260A-482B-BC86-7D6DEA9D8984</ServiceCollectionId>
<ServiceCollectionName xmlns="Company.Domain.Name.Space">Rich_Gold</ServiceCollectionName>
<Services xmlns="Company.Domain.Name.Space">Rich_Gold</Services>
<TunerPosition xmlns="Company.Domain.Name.Space">1</TunerPosition>
</MapItem>
<MapItem>
<EpgId xmlns="Company.Domain.Name.Space">000010FA-0000-0000-0000-000000000000</EpgId>
<MapId xmlns="Company.Domain.Name.Space">5DF26284-D0EA-4071-9DA0-22E463314D65</MapId>
<ServiceCollectionId xmlns="Company.Domain.Name.Space">83CFD40E-C7FB-420D-B9FC-5E5B711B9E74</ServiceCollectionId>
<ServiceCollectionName xmlns="Company.Domain.Name.Space">G-D9154-DF8-01_SC</ServiceCollectionName>
<Services xmlns="Company.Domain.Name.Space">G-D9154-DF8-PIP-01, G-D9154-DF8-FS-01</Services>
<TunerPosition xmlns="Company.Domain.Name.Space">2</TunerPosition>
</MapItem>
<ArrayOfMapItem>
<ArrayOfArrayOfGrant>
<ArrayOfGrant>
<Grant ResourceId="5df26284-d0ea-4071-9da0-22e463314d65" PrincipalExternalId="roman" PrincipalType="Group" ResType="Package" Right="Record">
<Conditions xmlns="http://www.company.com/egtv/bss">
<TimeExpiration Start="2014-05-01T07:00:00" End="9999-12-31T23:59:59.997" Type="TimeExpiration" Expiration="9999-12-31T23:59:59" />
</Conditions>
</Grant>
<Grant ResourceId="5df26284-d0ea-4071-9da0-22e463314d65" PrincipalExternalId="PETSIN" PrincipalType="Group" ResType="Package" Right="Record">
<Conditions xmlns="http://www.company.com/egtv/bss">
<TimeExpiration Start="2014-04-04T18:52:24.867" End="9999-12-31T23:59:59.997" Type="TimeExpiration" Expiration="9999-12-31T23:59:59" />
</Conditions>
</Grant>
<Grant ResourceId="5df26284-d0ea-4071-9da0-22e463314d65" PrincipalExternalId="PETSIN" PrincipalType="Group" ResType="Package" Right="Record">
<Conditions xmlns="http://www.company.com/egtv/bss">
<TimeExpiration Start="2014-04-04T18:53:28.797" End="9999-12-31T23:59:59.997" Type="TimeExpiration" Expiration="9999-12-31T23:59:59" />
</Conditions>
</Grant>
<Grant ResourceId="5df26284-d0ea-4071-9da0-22e463314d65" PrincipalExternalId="PETSIN" PrincipalType="Group" ResType="Package" Right="Record">
<Conditions xmlns="http://www.company.com/egtv/bss">
<TimeExpiration Start="2014-04-04T19:17:42.983" End="9999-12-31T23:59:59.997" Type="TimeExpiration" Expiration="9999-12-31T23:59:59" />
</Conditions>
</Grant>
</ArrayOfGrant>
<ArrayOfGrant>
<Grant ResourceId="6f26ecfd-4bfe-4c5d-af0b-164a93f448e8" PrincipalExternalId="roman" PrincipalType="Group" ResType="Package" Right="Record">
<Conditions xmlns="http://www.company.com/egtv/bss">
<TimeExpiration Start="2014-05-01T07:00:00" End="9999-12-31T23:59:59.997" Type="TimeExpiration" Expiration="9999-12-31T23:59:59" />
</Conditions>
</Grant>
</ArrayOfGrant>
</ArrayOfArrayOfGrant>
</root>
我试过这个:
XmlSerializer mySerializer = new XmlSerializer(typeof(MapItem[]), new XmlRootAttribute("ArrayOfMapItem"));
using (FileStream fs = new FileStream("DataMerged.xml", FileMode.Open))
{
MapItem[] r;
r = (MapItem[]) mySerializer.Deserialize(fs);
.....
}
但是当代码到达“mySerializer.Deserialize”时,它会得到:
InnerException: System.InvalidOperationException
HResult=-2146233079
Message=<root xmlns=''> was not expected.
Source=Microsoft.GeneratedCode
StackTrace:
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderChannelMapItemArray.Read3_ArrayOfChannelMapItem()
有没有一种方法可以从一个合并的文件中单独反序列化对象?当我反序列化对象时,它们仍然在单独的文件中,我没有问题。
感谢任何人可以提供的帮助
一个简单的方法是将 XML 加载到 XDocument
中,挑选出每个部分,然后使用现有的序列化代码分别反序列化每个部分。
首先,一些扩展方法:
public static class XObjectExtensions
{
public static T Deserialize<T>(this XElement element)
{
return element.Deserialize<T>(new XmlSerializer(typeof(T)));
}
public static T Deserialize<T>(this XElement element, XmlSerializer serial)
{
using (var reader = element.CreateReader())
{
object result = serial.Deserialize(reader);
if (result is T)
return (T)result;
}
return default(T);
}
}
然后,执行:
var xml = GetXml(); // Load the XML. (In my test code it's just a string literal.)
var doc = XDocument.Parse(xml); // In your case, you would use XDocument.Load(filename)
var mapXml = doc.Root.Element("ArrayOfMapItem");
var grantXml = doc.Root.Element("ArrayOfArrayOfGrant");
if (mapXml != null)
{
var mapItems = mapXml.Deserialize<MapItem[]>();
Debug.WriteLine(mapItems.GetXml()); // Two items deserialized successfully.
}
if (grantXml != null)
{
var grantItems = grantXml.Deserialize<Grant[][]>();
Debug.WriteLine(grantItems.GetXml()); // Two arrays of arrays deserialized successfully.
}
出于测试目的,我使用了您 类 的以下缩写版本:
[XmlType("MapItem", Namespace="")]
public class MapItem
{
[XmlElement(Namespace="Company.Domain.Name.Space")]
public string EpgId { get; set; }
}
[XmlType("Grant", Namespace="")]
public class Grant
{
[XmlAttribute("ResourceId")]
public string ResourceId { get; set; }
[XmlAttribute("PrincipalExternalId")]
public string PrincipalExternalId { get; set; }
}
我正在将两个对象序列化为 XML 并写入两个单独的 XML 文件,然后将这两个文件合并为一个文件。我想要做的是能够从合并文件中单独反序列化每个对象。
<?xml version="1.0" encoding="utf-8"?>
<root>
<ArrayOfMapItem>
<MapItem>
<EpgId xmlns="Company.Domain.Name.Space">0000DAC2-0000-0000-0000-000000000000</EpgId>
<MapId xmlns="Company.Domain.Name.Space">5D195A5B-FBBF-4042-8AB3-E4558CA1D347</MapId>
<ServiceCollectionId xmlns="Company.Domain.Name.Space">657A62F8-260A-482B-BC86-7D6DEA9D8984</ServiceCollectionId>
<ServiceCollectionName xmlns="Company.Domain.Name.Space">Rich_Gold</ServiceCollectionName>
<Services xmlns="Company.Domain.Name.Space">Rich_Gold</Services>
<TunerPosition xmlns="Company.Domain.Name.Space">1</TunerPosition>
</MapItem>
<MapItem>
<EpgId xmlns="Company.Domain.Name.Space">000010FA-0000-0000-0000-000000000000</EpgId>
<MapId xmlns="Company.Domain.Name.Space">5DF26284-D0EA-4071-9DA0-22E463314D65</MapId>
<ServiceCollectionId xmlns="Company.Domain.Name.Space">83CFD40E-C7FB-420D-B9FC-5E5B711B9E74</ServiceCollectionId>
<ServiceCollectionName xmlns="Company.Domain.Name.Space">G-D9154-DF8-01_SC</ServiceCollectionName>
<Services xmlns="Company.Domain.Name.Space">G-D9154-DF8-PIP-01, G-D9154-DF8-FS-01</Services>
<TunerPosition xmlns="Company.Domain.Name.Space">2</TunerPosition>
</MapItem>
<ArrayOfMapItem>
<ArrayOfArrayOfGrant>
<ArrayOfGrant>
<Grant ResourceId="5df26284-d0ea-4071-9da0-22e463314d65" PrincipalExternalId="roman" PrincipalType="Group" ResType="Package" Right="Record">
<Conditions xmlns="http://www.company.com/egtv/bss">
<TimeExpiration Start="2014-05-01T07:00:00" End="9999-12-31T23:59:59.997" Type="TimeExpiration" Expiration="9999-12-31T23:59:59" />
</Conditions>
</Grant>
<Grant ResourceId="5df26284-d0ea-4071-9da0-22e463314d65" PrincipalExternalId="PETSIN" PrincipalType="Group" ResType="Package" Right="Record">
<Conditions xmlns="http://www.company.com/egtv/bss">
<TimeExpiration Start="2014-04-04T18:52:24.867" End="9999-12-31T23:59:59.997" Type="TimeExpiration" Expiration="9999-12-31T23:59:59" />
</Conditions>
</Grant>
<Grant ResourceId="5df26284-d0ea-4071-9da0-22e463314d65" PrincipalExternalId="PETSIN" PrincipalType="Group" ResType="Package" Right="Record">
<Conditions xmlns="http://www.company.com/egtv/bss">
<TimeExpiration Start="2014-04-04T18:53:28.797" End="9999-12-31T23:59:59.997" Type="TimeExpiration" Expiration="9999-12-31T23:59:59" />
</Conditions>
</Grant>
<Grant ResourceId="5df26284-d0ea-4071-9da0-22e463314d65" PrincipalExternalId="PETSIN" PrincipalType="Group" ResType="Package" Right="Record">
<Conditions xmlns="http://www.company.com/egtv/bss">
<TimeExpiration Start="2014-04-04T19:17:42.983" End="9999-12-31T23:59:59.997" Type="TimeExpiration" Expiration="9999-12-31T23:59:59" />
</Conditions>
</Grant>
</ArrayOfGrant>
<ArrayOfGrant>
<Grant ResourceId="6f26ecfd-4bfe-4c5d-af0b-164a93f448e8" PrincipalExternalId="roman" PrincipalType="Group" ResType="Package" Right="Record">
<Conditions xmlns="http://www.company.com/egtv/bss">
<TimeExpiration Start="2014-05-01T07:00:00" End="9999-12-31T23:59:59.997" Type="TimeExpiration" Expiration="9999-12-31T23:59:59" />
</Conditions>
</Grant>
</ArrayOfGrant>
</ArrayOfArrayOfGrant>
</root>
我试过这个:
XmlSerializer mySerializer = new XmlSerializer(typeof(MapItem[]), new XmlRootAttribute("ArrayOfMapItem"));
using (FileStream fs = new FileStream("DataMerged.xml", FileMode.Open))
{
MapItem[] r;
r = (MapItem[]) mySerializer.Deserialize(fs);
.....
}
但是当代码到达“mySerializer.Deserialize”时,它会得到:
InnerException: System.InvalidOperationException
HResult=-2146233079
Message=<root xmlns=''> was not expected.
Source=Microsoft.GeneratedCode
StackTrace:
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderChannelMapItemArray.Read3_ArrayOfChannelMapItem()
有没有一种方法可以从一个合并的文件中单独反序列化对象?当我反序列化对象时,它们仍然在单独的文件中,我没有问题。
感谢任何人可以提供的帮助
一个简单的方法是将 XML 加载到 XDocument
中,挑选出每个部分,然后使用现有的序列化代码分别反序列化每个部分。
首先,一些扩展方法:
public static class XObjectExtensions
{
public static T Deserialize<T>(this XElement element)
{
return element.Deserialize<T>(new XmlSerializer(typeof(T)));
}
public static T Deserialize<T>(this XElement element, XmlSerializer serial)
{
using (var reader = element.CreateReader())
{
object result = serial.Deserialize(reader);
if (result is T)
return (T)result;
}
return default(T);
}
}
然后,执行:
var xml = GetXml(); // Load the XML. (In my test code it's just a string literal.)
var doc = XDocument.Parse(xml); // In your case, you would use XDocument.Load(filename)
var mapXml = doc.Root.Element("ArrayOfMapItem");
var grantXml = doc.Root.Element("ArrayOfArrayOfGrant");
if (mapXml != null)
{
var mapItems = mapXml.Deserialize<MapItem[]>();
Debug.WriteLine(mapItems.GetXml()); // Two items deserialized successfully.
}
if (grantXml != null)
{
var grantItems = grantXml.Deserialize<Grant[][]>();
Debug.WriteLine(grantItems.GetXml()); // Two arrays of arrays deserialized successfully.
}
出于测试目的,我使用了您 类 的以下缩写版本:
[XmlType("MapItem", Namespace="")]
public class MapItem
{
[XmlElement(Namespace="Company.Domain.Name.Space")]
public string EpgId { get; set; }
}
[XmlType("Grant", Namespace="")]
public class Grant
{
[XmlAttribute("ResourceId")]
public string ResourceId { get; set; }
[XmlAttribute("PrincipalExternalId")]
public string PrincipalExternalId { get; set; }
}