使用Serializable()从XML文件中填充数组

时间:2016-04-06 22:10:56

标签: c# xml serialization

我目前正在尝试使用[Serializable()]命令对象反序列化XML,我遇到了一些问题。这是代码示例:

using System;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.IO;

namespace XmlManipulation
{
    public class XmlManip
    {
        public static TestCasesList SerializeTest() //test function
        {
            TestCasesList testslist = null;
            string path = @"C:\Users\sxtx2987\Documents\Visual Studio 2015\Projects\FDB\deleteme\test.xml";

            XmlSerializer serializer = new XmlSerializer(typeof(TestCasesList));

            StreamReader reader = new StreamReader(path);

        testslist = (TestCasesList)serializer.Deserialize(reader);
        reader.Close();
        return testslist;
        }
    }


    [Serializable()]
    public class TestCase
    {
        [System.Xml.Serialization.XmlElement("name")]
        public string name;

        [System.Xml.Serialization.XmlElement("objective")]
        public string objective;

        [System.Xml.Serialization.XmlElement("criteria")]
        public string criteria;

        [System.Xml.Serialization.XmlElement("issue")]
        public string issue;

        [System.Xml.Serialization.XmlElement("clientcomments")]
        public string clientcomments;

        [System.Xml.Serialization.XmlElement("authoritycomments")]
        public string authoritycomments;
    }

    [Serializable()]
    [XmlType("testcaseslist")]
    public class TestCasesList
    {
        [XmlArray("testcase")]
        public TestCase[] TestCase { get; set; }
    }
}

这是我试图反序列化的文件

<xml version="1.00" encoding="UTF-8">
    <campaign>
        <name>Test XML</name>
        <number>XXXXXG04-06-1</number>
        <client>Fictional</client>
        <model>Rocket powered boots</model>
        <authority>Fictional authority</authority>
    </campaign>

    <testcaseslist>
        <testcase>
            <name>TestCase001</name>
            <objective>Objective test 1</objective>
            <criteria>Pass criteria test 1</criteria>
            <issue>Issue Description test 1</issue>
            <clientcomments>Client comments test 1</clientcomments>
            <authoritycomments>Authority comments test 1</authoritycomments>
        </testcase>

        <testcase>
            <name>TestCase002</name>
            <objective>Objective test 2</objective>
            <criteria>Pass criteria test 2</criteria>
            <issue>Issue Description test 2</issue>
            <clientcomments>Client comments test 2</clientcomments>
            <authoritycomments>Authority comments test 2</authoritycomments>
        </testcase>
    </testcaseslist>    
</xml>

我想要实现的是采取所有的根元素&#34; testcase&#34;并将每个子元素(即:name,objective,criteria,issue,clientcomments,authoritycomments)放在由多个类TestCase组成的类TestCasesList中。

所以在这个例子中:

TestCasesList

| - &GT; testcase 1

| - &GT; testcase 2

| - &GT;等....

包含测试用例的所有元素。

我上面的代码是我现在可以收集的代码,但由于这是我想要做的一个特定的操作,我找不到所有相关信息来解决我的问题。

代码不会抛出任何错误,但是当我尝试调用函数时

        TestCasesList test = null;

        test = XmlManipulation.XmlManip.SerializeTest();

我得到一个空的测试对象。<​​/ p>

我认为我的问题是XmlType和XmlArray部分,但经过几个小时的研究和试验,我仍然无法从XML获取信息。

感谢您的时间。

1 个答案:

答案 0 :(得分:1)

这里有一些问题。

  1. 根元素可能不是您认为的那样。您的代码假定<testcaseslist>是根元素。但实际上,以下是根元素:

    <xml version="1.00" encoding="UTF-8">
        <!-- XML Contents -->
    </xml>
    

    root 看起来像标准XML声明:

    <?xml version="1.0" encoding="UTF-8">
    

    但它在开头缺少问号<?xml>。所以你需要修改你的代码来处理它。您可以使用XmlReader跳过相应的元素,或反序列化相应的容器类型来完成此操作。

  2. <testcaseslist>内,元素<testcase>未归入容器元素下。因此,您需要使用[XmlElement("testcase")]而不是[XmlArray("testcase")]

  3. 要在类上声明根元素名称,您必须使用[XmlRoot("testcaseslist")]而不是[XmlType("testcaseslist")]

  4. 因此,您的TestCasesList应如下所示:

    [XmlRoot("testcaseslist")]
    public class TestCasesList
    {
        [XmlElement("testcase")]
        public TestCase[] TestCase { get; set; }
    }
    

    然后,要在您的XML中向前跳过并反序列化<testcaseslist>元素,请使用XmlReader.ReadToFollowing()

        public static TestCasesList Deserialize(TextReader reader)
        {
            using (var xmlReader = XmlReader.Create(reader))
            {
                // Skip to the <testcaseslist> element.
                if (!xmlReader.ReadToFollowing("testcaseslist", ""))
                    return null;
    
                var serializer = new XmlSerializer(typeof(TestCasesList));
                return (TestCasesList)serializer.Deserialize(xmlReader);
            }
        }
    

    readerStreamReader reader = new StreamReader(path);

    或者,使用容器类型:

    [XmlRoot("xml")]
    public class XmlRoot
    {
        public TestCasesList testcaseslist { get; set; }
    }
    

    你可以这样做:

        public static TestCasesList Deserialize(TextReader reader)
        {
            var serializer = new XmlSerializer(typeof(XmlRoot));
            var root = (XmlRoot)serializer.Deserialize(reader);
            return root == null ? null : root.testcaseslist;
        }
    

    通过从XML自动生成c#类,可以避免上述一些困难,例如:与http://xmltocsharp.azurewebsites.net/。有关详情,请参阅Generate C# class from XML

    顺便说一下,[Serializable]XmlSerializer没有影响。