如何解析混合重复和非重复子节点的节点?

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

让我们首先处理任何认为这可能是 的副本的想法,它只考虑这个结构,可以简单地表示为 things: thing[].

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

这道题是关于如何用classes.

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

这绝对不是数组。它 可以说是一本字典,但我们明确禁止将 IDictionary<T1,T2>XmlSerializer.

一起使用

通常我会从 classes 开始,让 XmlSerializer 告诉我 XML 格式,但是这个 XML 是由我无法控制的系统定义的。

使问题更加复杂的是字符串是密封的 class,因此您无法从它继承,因此无法为命名字段而对其进行别名。

如何反序列化具有混合重复和非重复子节点的节点?[​​=16=]

对我来说,它看起来像是一组不同类型的对象,它们可能继承相同的基础 class。我会做这样的事情:

[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; }
}

一旦找到它,答案就简单得令人尴尬:将 XmlElement 属性应用于数组成员。更多详情请见 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; }
}

然后我们可以将零次或多次出现的 d 解析为没有集合节点的直接子节点来拥有和键入它们,并将其解析为 thing 对象上的数组 属性。

为了阐明属性的作用,属性 thing.d 的值是一个 集合 ,其中的元素是匿名的,类型为字符串.序列化恰好反映了这一点,为您提供了一个集合节点 "d",其子节点的名称来自其类型:

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

但是,这不是我们要解析的内容。 [XmlElement] 属性防止 属性 被视为一个集合,如果它不是一个集合,那么它可以映射到 [=31] 的唯一 other 方式=] 作为重复元素。