将一组KeyValuePair序列化为XML

3

我正在尝试将一个对象序列化为XML。以下是我需要的XML格式。

<parameters>
  <parameter>
    <key>Key1</key>
    <value>Value1</value>
    <key>Key2</key>
    <value>Value2</value>
    <key>Key3</key>
    <value>value3</value>
  </parameter>
</parameters>

下面是我创建的模型。
[Serializable]
[XmlType("parameters")]
public class parameters
{
    public List<parameter<string,string>> parameter { get; set; }
}

[Serializable]
[XmlType("parameter")]
public class parameter<K,V>
{
    public K key { get; set; }
    public V value { get; set; }

    public parameter() { }

    public parameter(K key, V value)
    {
        this.key = key;
        this.value = value;
    }
}

当我尝试将其序列化为XML时,我得到了以下格式。
<parameters>
  <parameter>
    <parameter>
      <key>Key1</key>
      <value>Value1</value>
    </parameter>
    <parameter>
      <key>Key2</key>
      <value>Value2</value>
    </parameter>
    <parameter>
      <key>Key3</key>
      <value>Value3</value>
    </parameter>
  </parameter>
</parameters>

请帮我解决这个问题。

一个有效的 xml 必须包含一个根标签来容纳它的子元素。 - Amit Kumar Ghosh
你不需要多级参数。将XmlArray更改为XmlElement可以消除额外的标记层。 - jdweng
这完全不相关。根标记是<parameters>,它存在,并且很明显xml头部被省略以使问题更简洁;输出也没有显示它,而输出系统总是添加那些东西。该问题已经在三年前得到了回答和接受。这个答案没有增加任何价值。 - Nyerguds
2个回答

1

XmlSerializer 的角度来看,你的 XML 中的 <parameter> 元素不是一组键值对类的列表,因为每个键值对没有嵌套在某个包含元素中。相反,它是一个 多态列表,其中每个条目可以是 <key> 类型或 <value> 类型的元素。因此,处理这个问题最简单的方法可能是使用序列化程序的内置功能来处理多态类型的列表,方法如下:

public abstract class ParameterKeyOrValue<T>
{
    [XmlText]
    public T Text { get; set; }
}

public sealed class ParameterKey<T> : ParameterKeyOrValue<T>
{
}

public sealed class ParameterValue<T> : ParameterKeyOrValue<T>
{
}

[Serializable]
[XmlType("parameters")]
public class parameters
{
    [XmlIgnore]
    public List<parameter<string, string>> parameter { get; set; }

    [XmlArray("parameter")]
    [XmlArrayItem("key", typeof(ParameterKey<string>))]
    [XmlArrayItem("value", typeof(ParameterValue<string>))]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public ParameterKeyOrValue<string>[] XmlParameters
    {
        get
        {
            if (parameter == null)
                return null;
            return parameter.SelectMany(p => new ParameterKeyOrValue<string>[] { new ParameterKey<string> { Text = p.key }, new ParameterValue<string> { Text = p.value } }).ToArray();
        }
        set
        {
            if (value == null)
                parameter = null;
            else
            {
                if (value.Length % 2 != 0)
                    throw new ArgumentException("Unequal number of keys and values");
                var newParameters = value.OfType<ParameterKey<string>>().Zip(value.OfType<ParameterValue<string>>(), (k, v) => new parameter<string, string>(k.Text, v.Text)).ToList();
                // Make sure we got an equal number of keys and values.
                if (newParameters.Count != value.Length / 2)
                    throw new ArgumentException("Unequal number of keys and values");
                parameter = newParameters;
            }
        }
    }
}

[XmlArrayItem("someTypeName", typeof(SomeType))]装饰告诉序列化程序,类型为SomeType的数组元素(在本例中为ParameterKey<string>ParameterValue<string>)将以元素名称"someTypeName"(分别为"key""value")进行序列化。


0
你需要让参数包含一个键值列表(顺便说一下,.net有几个集合可以为你做到这一点,比如Dictionary),例如:
public class Parameter<K,V>{
  public Dictionary<K,V> Values {get; set;}

  public Parameter()
  {
     Values = new Dictionary<K,V>();
  }

  public void AddParameter(K key, V value)
  {
     Values.Add(key,value);
  }

  ...Other access methods here
}

或者在参数中将其作为键值对列表或字典:

public class Parameters<K,V>{

   public Dictionary<K,V> Parameters {get; set;}

   public Parameters(){
       Parameters = new Dictionary<K,V>();
   }
}

显然第二个选项是最好的,因为第一个选项只是重新发明了 .net 字典。第一个选项似乎没有任何好处。

这是基础知识,如果你不真正理解数组和 .net 集合,你应该熟悉这个领域。在 stack overflow 上搜索将给你所需的一切。

您可以使用 XmlElementAttribute.ElementName 属性来命名 Parameters 字典,以您喜欢的方式命名,它应该产生您想要的结果,尽管我会质疑为什么在参数节点内您只想要一个参数节点?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接