使用叶元素上的属性将类序列化为XML时的冗余元素

时间:2013-04-22 00:49:08

标签: c# .net xml xml-serialization

我有以下类序列,我想序列化为XML:

public class Foo
{
    [XmlArray("approxPriceList")]
    [XmlArrayItem("approxPrice")]
    public List<ApproxPriceElement> ApproxPriceList { get; set; }
}

public class ApproxPriceElement
{
    [XmlAttribute("currency")]
    public string Currency { get; set; }

    [XmlElement("approxPrice")]
    public decimal? ApproxPrice { get; set; }
}

如果我序列化Foo,我会得到以下XML:

<approxPriceList>
    <approxPrice currency="aud">
        <approxPrice>2220.00</approxPrice>
    </approxPrice>
</approxPriceList>

我想要的是以下内容:

<approxPriceList>
    <approxPrice currency="aud">2220.00</approxPrice>
</approxPriceList>

一种想法是将ApproxPriceList中的Foo更改为List<decimal?>,但后来我无法弄清楚如何将currency属性与每个{{1}相关联在列表中。

有没有办法实现这个目标?

2 个答案:

答案 0 :(得分:1)

使用XmlText代替XmlElement("approxPrice")

[XmlText]
public decimal? ApproxPrice { get; set; }

要允许元素null添加此内容:

[XmlArrayItem("approxPrice", IsNullable = true)]
public List<ApproxPriceElement> ApproxPriceList { get; set; }

以下是“无法用于编码复杂类型”异常(source)的建议解决方法:

  [XmlText]
  public decimal ApproxPrice { get; set; }
  [XmlIgnore]
  public bool ApproxPriceSpecified { get { return ApproxPrice >= 0; } }

答案 1 :(得分:0)

您可以使用IXmlSerializable

public class Foo : IXmlSerializable
    {
        public Foo()
        {
            ApproxPriceList = new List<ApproxPriceElement>();
        }

        public List<ApproxPriceElement> ApproxPriceList { get; set; }

        public XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
            while (reader.Read())
            {
                if (reader.IsStartElement())
                {
                    switch (reader.LocalName)
                    {
                        case "approxPrice":
                            {
                                var approxPrice = new ApproxPriceElement();

                                approxPrice.Currency = reader.GetAttribute("currency");

                                var approxPriceValue = reader.ReadElementContentAsString();

                                if (!string.IsNullOrEmpty(approxPriceValue))
                                {
                                    approxPrice.ApproxPrice = decimal.Parse(approxPriceValue);
                                }

                                ApproxPriceList.Add(approxPrice);
                            }
                            break;
                    }
                }
            }
        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteStartElement("approxPriceList");
            foreach (var approxPrice in ApproxPriceList)
            {
                writer.WriteStartElement("approxPrice");
                writer.WriteAttributeString("currency", approxPrice.Currency);
                writer.WriteString(approxPrice.ApproxPrice.ToString());
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
        }
    }

    public class ApproxPriceElement
    {
        public string Currency { get; set; }

        public decimal? ApproxPrice { get; set; }
    }

这不方便,但它可以胜任。