XmlSerializer - 序列化没有父元素的列表元素

时间:2016-02-03 12:24:54

标签: c# xml serialization xsd

我知道他的问题已经被提出并得到了回答,但我有一种不同的情况,解决方案并没有起作用。我有一个web方法响应xsd,我需要序列化/反序列化。下面是xsd的片段,这是有问题的。

<xs:choice minOccurs="0">
  <xs:element name="Type1" maxOccurs="unbounded">
    <xs:complexType>
      <xs:sequence>
        <xs:element type="xs:string" name="string1"/>
        <xs:element type="xs:string" name="string2"/>
        <xs:element type="xs:boolean" name="boolean1"/>                           
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="Type2">
    <xs:complexType>
      <xs:sequence>
        <xs:element type="xs:float" name="float1"/>
        <xs:element type="xs:float" name="float2"/>
        <xs:element type="xs:float" name="float3"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:choice>

我已经定义了这个选择元素,如下所示:

public class Type1
{
    [XmlElement(IsNullable = true)]
    public string string1 { get; set; }

    [XmlElement(IsNullable = true)]
    public string string2 { get; set; }

    public bool boolean1 { get; set; }
}

public class Type2
{
    public float float1 { get; set; }

    public float float { get; set; }

    public float float3 { get; set; }
}

[XmlElement("Type1", typeof(List<Type1>), IsNullable = true)]
[XmlElement("Type2", typeof(Type2), IsNullable = true)]
public object Type { get; set; }

问题是当我需要序列化Type1元素列表时。我明白了:

<Type1>
  <Type1>
     <string1>6185</string1>
     <string2>VW</string2>
     <boolean1>true</boolean1>
  </Type1>
  <Type1>
     <string1>6186</string1>
     <string2>AUDI</string2>
     <boolean1>true</boolean1>
  </Type1>
  <Type1>
     <string1>6187</string1>
     <string2>OPEL</string2>
     <boolean1>true</boolean1>
  </Type1>
</Type1>

当我根据xsd,需要得到这个:

<Type1>
   <string1>6185</string1>
   <string2>VW</string2>
   <boolean1>true</boolean1>
</Type1>
<Type1>
   <string1>6186</string1>
   <string2>AUDI</string2>
   <boolean1>true</boolean1>
</Type1>
<Type1>
   <string1>6187</string1>
   <string2>OPEL</string2>
   <boolean1>true</boolean1>
</Type1>

所以我的问题是,如何摆脱那个父元素&#34; Type1&#34;那封装了所有Type1列表元素?

谢谢!

1 个答案:

答案 0 :(得分:0)

为了生成您想要的XML,您可能需要稍微更改数据模型。

XmlSerializer支持单个多态元素或多态元素集合。在这两种情况下,它会查看每个元素的名称以确定反序列化时的实际类型。在您的情况下,您希望拥有一种类型的集合或第二种类型的单一集合。您已经通过指定XmlSerializer有效地将集合视为类型为List<Type1>的单例来实现此设计 - 这将需要列表的外部容器元素。

由于您不希望这样,您可以指定您的Type属性是每种类型的多态元素的集合:

    [XmlElement("Type1", typeof(Type1), IsNullable = true)]
    [XmlElement("Type2", typeof(Type2), IsNullable = true)]
    public List<object> Type

如果要保留当前的数据模型,可以创建一个将Type打包到数组中的代理属性,验证该数组是包含第一个类型的集合还是第二个类型的单个集合: / p>

[XmlRoot("Root")]
public class RootObject
{
    [XmlElement("Type1", typeof(Type1), IsNullable = true)]
    [XmlElement("Type2", typeof(Type2), IsNullable = true)]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public object [] TypeArray
    {
        get
        {
            if (Type == null)
                return null;
            var collection = Type as IEnumerable;
            if (collection != null)
                return collection.Cast<object>().ToArray();
            else
                return new[] { Type };
        }
        set
        {
            if (value == null)
            {
                Type = null;
                return;
            }
            var type1 = value.OfType<Type1>().ToList();
            var type2 = value.Where(t => t == null || t is Type2).Cast<Type2>().ToList();
            if (type2.Count == 1 && type1.Count == 0)
                Type = type2[0];
            else if (type1.Count == value.Length)
                Type = type1;
            else
                throw new InvalidOperationException("invalid value");
        }
    }

    [XmlIgnore]
    public object Type { get; set; }
}

原型fiddle