本文介绍了如何使用动态元素名称反序列化XML?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的XML如下:

<rates>
    <rate1>1250.00</rate1>
    <rate2>1900.00</rate2>
</rates>

这在我的可序列化类中:

This is in my Serializable class:

[XmlRoot("main")]
public class Main
{
    [XmlArray("rates"), XmlAnyElement]
    public Rates Rates { get; set; }
}

public class Rates : List<Rate> { }

public class Rate
{
    [XmlAnyElement]
    public string Rate;
}

如何反序列化XML,以便可以使用以下方式访问它:

How can I deserialize the XML so that I can access it using:

var rate1 = Main.Rates[0].Rate;
var rate2 = Main.Rates[1].Rate;


推荐答案

您可以通过将费率集合:

You can do this by having your Rates collection implement IXmlSerializable:

public class Rates : List<Rate>, IXmlSerializable
{
    public Rates() : base() { }
    public Rates(IEnumerable<Rate> collection) : base(collection) { }

    #region IXmlSerializable Members

    XmlSchema IXmlSerializable.GetSchema()
    {
        return null;
    }

    void IXmlSerializable.ReadXml(XmlReader reader)
    {
        // for the `decodeName` delegate, you could check that the node name matches the pattern "rateN" for some integer N, if you want.
        XmlKeyValueListHelper.ReadXml(reader, this, null, s => new Rate { RateValue = s });
    }

    void IXmlSerializable.WriteXml(XmlWriter writer)
    {
        XmlKeyValueListHelper.WriteXml(writer, this, (i, rate) => "rate" + XmlConvert.ToString(i), r => r.RateValue);
    }

    #endregion
}

public class Rate
{
    public string RateValue;
}

public static class XmlKeyValueListHelper
{
    const string XsiNamespace = @"http://www.w3.org/2001/XMLSchema-instance";
    const string XsiNil = "nil";

    public static void WriteXml<T>(XmlWriter writer, IEnumerable<T> collection, Func<int, T, string> encodeName, Func<T, string> encodeValue)
    {
        int i = 0;
        foreach (var item in collection)
        {
            writer.WriteStartElement(XmlConvert.EncodeLocalName(encodeName(i, item)));
            if (item == null)
            {
                writer.WriteAttributeString(XsiNil, XsiNamespace, XmlConvert.ToString(true));
            }
            else
            {
                writer.WriteValue(encodeValue(item) ?? "");
            }
            writer.WriteEndElement();
            i++;
        }
    }

    public static void ReadXml<T>(XmlReader reader, ICollection<T> collection, Func<int, string, bool> decodeName, Func<string, T> decodeValue)
    {
        if (reader.IsEmptyElement)
        {
            reader.Read();
            return;
        }

        int i = 0;
        reader.ReadStartElement(); // Advance to the first sub element of the list element.
        while (reader.NodeType == XmlNodeType.Element)
        {
            var key = XmlConvert.DecodeName(reader.Name);
            if (decodeName == null || decodeName(i, key))
            {
                var nilValue = reader[XsiNil, XsiNamespace];
                if (!string.IsNullOrEmpty(nilValue) && XmlConvert.ToBoolean(nilValue))
                {
                    collection.Add(default(T));
                    reader.Skip();
                }
                else
                {
                    string value;
                    if (reader.IsEmptyElement)
                    {
                        value = string.Empty;
                        // Move past the end of item element
                        reader.Read();
                    }
                    else
                    {
                        // Read content and move past the end of item element
                        value = reader.ReadElementContentAsString();
                    }
                    collection.Add(decodeValue(value));
                }
            }
            else
            {
                reader.Skip();
            }
            i++;
        }
        // Move past the end of the list element
        reader.ReadEndElement();
    }
}

示例。

这篇关于如何使用动态元素名称反序列化XML?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 10:19