简体   繁体   中英

Deserialising XML with different element name in c#

XML:

<?xml version="1.0" encoding="UTF-8"?>
<Images>
    <I0>
        <Path>123.com</Path>
    <I0>
    <I1>
        <Path>123.com</Path>
    <I1>
    <I2>
        <Path>123.com</Path>
    <I2>
</Images>

Can serializer.Deserialize() be used to get tags with different names into a collection?

currently, in my object I have:

C#:

public class rootObject
{
    [XmlElement(ElementName = "I0")]
    public I0 I0 { get; set; }
    [XmlElement(ElementName = "I1")]
    public I1 I1 { get; set; }
    [XmlElement(ElementName = "I2")]
    public I2 I2 { get; set; }

}

But I would like to have (Because Images can have more or fewer elements):

public class rootObject
{
    public List<I> Is  { get; set; }
}

You can do what you are suggesting you just merely need to pass in the type argument in your class doing the generic. The key point to remember when you do a deserialization routine is that the routine needs to know the sub reference. So if I was to say string.Deserialize it would bomb. It would need to know a reference string.Deserialize> where Sub could be the class object that may change.

Say I have a base class and I want 'T' to be a type I can change for extensible abilities later.

[Serializable]
public class Test<T> where T : class
{
    public Test() { }

    public int TestId { get; set; }
    public string Name { get; set; }
    public List<T> Shipments { get; set; }
}

I want to test this with two classes I just make up that have different properties slightly

[Serializable]
public class Sub1
{
    public int Id { get; set; }
    public string Desc { get; set; }
}

[Serializable]
public class Sub2
{
    public int IdWhatever { get; set; }
    public string DescWhatever { get; set; }
}

Now let's do a main program and test serialization.

class Program
{
    static void Main(string[] args)
    {
      var serializeTest = new Test<Sub1> { TestId = 1, Name = "Test", Shipments = new List<Sub1> { new Sub1 { Id = 1, Desc = "Test" }, new Sub1 { Id = 2, Desc = "Test2" } } };
      var serializeTest2 = new Test<Sub2> { TestId = 1, Name = "Test", Shipments = new List<Sub2> { new Sub2 { IdWhatever = 1, DescWhatever = "Test" }, new Sub2 { IdWhatever = 2, DescWhatever = "Test2" } } };
      var serialized = serializeTest.SerializeToXml();
      var serialized2 = serializeTest2.SerializeToXml();
      var deserialized = serialized.DeserializeXml<Test<Sub1>>();
      var deserialized2 = serialized2.DeserializeXml<Test<Sub2>>();

      Console.WriteLine(serialized);
      Console.WriteLine();
      Console.WriteLine(serialized2);
      Console.ReadLine();
    }
}

And my Serialize and DeSerialize extension methods:

public static string SerializeToXml<T>(this T valueToSerialize, string namespaceUsed = null)
{
      var ns = new XmlSerializerNamespaces(new XmlQualifiedName[] { new XmlQualifiedName(string.Empty, (namespaceUsed != null) ? namespaceUsed : string.Empty) });
      using (var sw = new StringWriter())
      {
        using (XmlWriter writer = XmlWriter.Create(sw, new XmlWriterSettings { OmitXmlDeclaration = true }))
        {
          dynamic xmler = new XmlSerializer(typeof(T));
          xmler.Serialize(writer, valueToSerialize, ns);
        }

        return sw.ToString();
      }
}

public static T DeserializeXml<T>(this string xmlToDeserialize)
{
  dynamic serializer = new XmlSerializer(typeof(T));

  using (TextReader reader = new StringReader(xmlToDeserialize))
  {
    return (T)serializer.Deserialize(reader);
  }
}

You don't need to specify the XmlElement name when the properties match the XML. A few solutions, some kinda hacky :).

  1. HACKY: use regex string replace to replace <I#> and </I#> to just <I> and </I>
  2. SOMEWHAT HACKY: This might work for you: How to deserialize an XML array containing multiple types of elements in C# , but you'd have to add an attribute for i0, i1 ... i100, etc.
  3. BEST: Is that your entire XML? I'd honestly just use LINQToXml and do a Descendants("Path") and get an array of strings back with 1 line of code. Serialization is not really the best solution for this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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