web-dev-qa-db-ja.com

XmlArrayを使用したxmlファイルの逆シリアル化?

このxml構造を逆シリアル化しようとしています。

<?xml version="1.0"?>
<DietPlan>
    <Health>
        <Fruit>Test</Fruit>
        <Fruit>Test</Fruit>
        <Veggie>Test</Veggie>
        <Veggie>Test</Veggie>
    </Health>
</DietPlan>

そして私は試しました:

[Serializable]
[XmlRoot(ElementName = "DietPlan")]
public class TestSerialization
{
    [XmlArray("Health")]
    [XmlArrayItem("Fruit")]
    public string[] Fruits { get; set; }

    [XmlArray("Health")]
    [XmlArrayItem("Veggie")]
    public string[] Veggie { get; set; }
}

ただし、これにより、「XML要素は現在のスコープにすでに存在します。XML属性を使用して、要素に別のXML名または名前空間を指定してください」という例外がスローされます。事前に感謝します。

XMLを逆シリアル化できるようにするには、共通の型が必要です。これを使用して、以下に示すように、要素の名前に応じてインスタンス化する型を[XmlElement]名前空間で定義できます。

public class StackOverflow_15907357
{
    const string XML = @"<?xml version=""1.0""?>
                        <DietPlan>
                            <Health>
                                <Fruit>Test</Fruit>
                                <Fruit>Test</Fruit>
                                <Veggie>Test</Veggie>
                                <Veggie>Test</Veggie>
                            </Health>
                        </DietPlan>";

    [XmlRoot(ElementName = "DietPlan")]
    public class TestSerialization
    {
        [XmlArray("Health")]
        [XmlArrayItem("Fruit", Type = typeof(Fruit))]
        [XmlArrayItem("Veggie", Type = typeof(Veggie))]
        public Food[] Foods { get; set; }
    }

    [XmlInclude(typeof(Fruit))]
    [XmlInclude(typeof(Veggie))]
    public class Food
    {
        [XmlText]
        public string Text { get; set; }
    }

    public class Fruit : Food { }
    public class Veggie : Food { }

    public static void Test()
    {
        MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(XML));
        XmlSerializer xs = new XmlSerializer(typeof(TestSerialization));
        TestSerialization obj = (TestSerialization)xs.Deserialize(ms);
        foreach (var food in obj.Foods)
        {
            Console.WriteLine("{0}: {1}", food.GetType().Name, food.Text);
        }
    }
}
27
carlosfigueira