How to parse nodes with mixed repeating and non-repeating child nodes?

Let’s start by disposing of any notion that this might be a duplicate of How to read xml document in MVC core (1.0.0)? which considers only this structure, trivially expressible as things: thing[].

<things>
  <thing>..</thing>
  <thing>..</thing>
  <thing>..</thing>
  
</things>

This question is about how to express the following as classes.

<things>
  <a>..</a>
  <b>..</b>
  <c>..</c>
  <d>..</d>
  <d>..</d>
  <d>..</d>
  
</things>

This is absolutely not an array. It is arguably a dictionary but we are expressly forbidden from using IDictionary<T1,T2> with XmlSerializer.

Normally I would start with the classes and let XmlSerializer tell me the XML format, but this XML is defined by a system out of my control.

Compounding the problem is the fact that string is a sealed class, so you can’t inherit from it, making it impossible to alias it for the purpose of naming the fields.

How do I deserialise a node with mixed repeating and non-repeating child nodes?


Answer: How to parse nodes with mixed repeating and non-repeating child nodes?

Kirill Polishchuk – For me it looks like an array of objects of different types which possibly inherit same base class. I would do something like this:

[XmlInclude(typeof(A))]
[XmlInclude(typeof(B))]
...
public class BaseClass {}

[XmlRoot("a")]
public class A : BaseClass { }

[XmlRoot("b")]
public class B : BaseClass { }
...

public class Things
{
   [XmlElement("things")]
   public BaseClass[] Items { get; set; }
}

Peter Wone – Once you find it, the answer is embarrassingly simple: you apply the XmlElement attribute to the array member. Further details at https://docs.microsoft.com/en-us/dotnet/standard/serialization/controlling-xml-serialization-using-attributes#serializing-an-array-as-a-sequence-of-elements

public class thing {
  public string a { get; set; }
  public string b { get; set; }
  public string c { get; set; }
  [XmlElement]
  public string[] d { get; set; }
}

We can then parse zero or more occurrences of d as direct children without a collection node to own and type them, into an array property on our thing object.

To clarify the effect of the attribute, the value of the property thing.d is a collection in which the elements are anonymous and have type string. Serialisation exactly reflects this, giving you a collection node “d” with child nodes that get their names from their type:

<things>
  <a>..</a>
  <b>..</b>
  <c>..</c>
  <d>
    <string>..</string>
    <string>..</string>
    
  </d>
</things>

However, this is not what we are trying to parse. The [XmlElement] attribute prevents the property from being treated as a collection, and if it isn’t a collection the only other way it can map to XML is as a repeating element.

Check Also

[Download] Rom Global for Samsung Galaxy Note8 Korea

[Download] Rom Global for Samsung Galaxy Note8 Korea Global rom for Samsung Galaxy Note 8 …

Trả lời

Thư điện tử của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *