从一个 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; }
}