0

XML Serialization を使用して xml ドキュメントを作成しました。

このように見えます

<?xml version="1.0" encoding="utf-8"?>
<Course xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <courseName>Comp 1510</courseName>
  <backgroundColor>#ffffff</backgroundColor>
  <fontColor>#ffffff</fontColor>
  <sharingKey>ed35d1f8-6be1-4f87-b77f-c70298e5abbb</sharingKey>
  <task type="Assignment">
    <taskName>First Task</taskName>
    <description>description</description>
    <taskDueDate>2010-01-24T12:41:20.0321826-08:00</taskDueDate>
    <weight xsi:nil="true" />
    <beforeDueDateNotification>30</beforeDueDateNotification>
    <outOf>50.4</outOf>
  </task>
</Course>

これを作るための私のコード

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace ConsoleApplication1
{
    [XmlRoot("Course")]
    public class MyWrapper 
    {
        public MyWrapper()
        {
            TaskList = new List<Tasks>();
        }

        [XmlElement("courseName")]
        public string CourseName { get; set; }

        [XmlElement("backgroundColor")]
        public string BackgroundColor { get; set; }

        [XmlElement("fontColor")]
        public string  FontColor { get; set; }

        [XmlElement("sharingKey")]
        public Guid SharingKey { get; set; }

        [XmlElement("task")]
        public List<Tasks> TaskList { get; set; }

    }

public class Tasks
{
    [XmlAttribute("type")]
    public string Type { get; set; }

    [XmlElement("taskName")]
    public string TaskName { get; set; }

    [XmlElement("description")]
    public string Description { get; set; }

    [XmlElement("taskDueDate")]
    public DateTime TaskDueDate { get; set; }

    [XmlElement("weight")]
    public decimal? Weight { get; set; }

    [XmlElement("beforeDueDateNotification")]
    public int BeforeDueDateNotification { get; set; }

    [XmlElement("outOf")]
    public decimal? OutOf { get; set; }

}

}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {

            MyWrapper wrap = new MyWrapper();
            wrap.CourseName = "Comp 1510";
            wrap.FontColor = "#ffffff";
            wrap.BackgroundColor = "#ffffff";
            wrap.SharingKey = Guid.NewGuid();

            Tasks task = new Tasks()
            {
                TaskName = "First Task",
                Type = "Assignment",
                TaskDueDate = DateTime.Now,
                Description = "description",
                BeforeDueDateNotification = 30,
                OutOf = 50.4M
            };

            wrap.TaskList.Add(task);
            SerializeToXML(wrap);

           var grab = DeserializeFromXML();

           foreach (var item in grab)
           {

           }
        }

        static public void SerializeToXML(MyWrapper list)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(MyWrapper));
            TextWriter textWriter = new StreamWriter(@"C:\New folder\test.xml");
            serializer.Serialize(textWriter, list);
            textWriter.Close();
        }

        static List<MyWrapper> DeserializeFromXML()
        {
            XmlSerializer deserializer = new XmlSerializer(typeof(List<MyWrapper>));
            TextReader textReader = new StreamReader(@"C:\New folder\test.xml");
            List<MyWrapper> tasks;
            tasks = (List<MyWrapper>)deserializer.Deserialize(textReader);
            textReader.Close();

            return tasks;
        }
    }
}

今、シリアル化を解除しようとすると、このエラーが発生します

System.InvalidOperationException was unhandled
  Message="There is an error in XML document (2, 2)."
  Source="System.Xml"
  StackTrace:
       at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
       at System.Xml.Serialization.XmlSerializer.Deserialize(TextReader textReader)
       at ConsoleApplication1.Program.DeserializeFromXML() in C:\Users\chobo2\Desktop\ConsoleApplication1\ConsoleApplication1\Program.cs:line 55
       at ConsoleApplication1.Program.Main(String[] args) in C:\Users\chobo2\Desktop\ConsoleApplication1\ConsoleApplication1\Program.cs:line 34
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: System.InvalidOperationException
       Message="<Course xmlns=''> was not expected."
       Source="ap72r7cf"
       StackTrace:
            at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderList1.Read5_ArrayOfMyWrapper()
       InnerException: 

なぜこれが起こっているのかわかりません。

いくつかの副次的な質問 - 主な問題が解決された後に回答してください

必要がない限り、これら 2 つの質問について新しいフォーラム投稿を作成したくありませんでした。

  1. オブジェクト型を与えることが重要なのはなぜですか? すべてのフィールドを文字列として作成しないのはなぜですか?

        [XmlElement("sharingKey")]
        public Guid SharingKey { get; set; }
    

この場合、Guid を取得するのは、シリアル化を解除するときだけなので、後で文字列から Guid に変換する必要はありませんか?

これが正しければ、他の人から xml ファイルを取得し、それをデシリアライズしたい場合、そこからどのオブジェクトが出てくるかをどのように知ることができますか? たとえば、私の「OutOf」が実際に null 許容の 10 進数の型であることをどのように知ることができますか? 実際、C# はどのようにしてそれを認識しているのでしょうか。これがそのタイプであるということを示唆するものは何も見当たりません。

  1. 実際にシリアル化を解除するとき、どうすれば foreach ループを作成できるのか疑問に思っています。「MyWrapper」オブジェクトのリストをそれぞれ調べたいので。しかし、MyWrapper には Task オブジェクトのコレクションがあります。では、foreach ループ内に for ループを作成する必要がありますか? それとももっと良い方法がありますか?

ありがとう

4

2 に答える 2

1

さて、問題は次のとおりだと思います。単一MyWrapperのをシリアル化していますが、逆シリアル化しようとしていますList<MyWrapper>

それはうまくいきません.単一のオブジェクトをファイルにシリアル化MyWrapperすると、そのファイルから逆シリアル化すると単一のオブジェクトが返されます.

逆シリアル化を次のように変更します。

    static MyWrapper DeserializeFromXML()
    {
        XmlSerializer deserializer = new XmlSerializer(typeof(MyWrapper));
        TextReader textReader = new StreamReader(@"C:\New folder\test.xml");
        MyWrapper tasks = (MyWrapper)deserializer.Deserialize(textReader);
        textReader.Close();
        return tasks;
    }

そして物事は再びうまくいくはずです。

于 2010-01-24T21:10:52.500 に答える
1

の単一のインスタンスをシリアル化しようとしていますがMyWrapper、それらのリストとして逆シリアル化します。いずれかの方法 (どちらかの方法) に固執すると、問題なく動作します。例えば:

static public void SerializeToXML(MyWrapper wrapper)
{
    XmlSerializer serializer = new XmlSerializer(typeof(List<MyWrapper>));
    using (TextWriter textWriter = File.CreateText("test.xml"))
    {
        // Create single-element list
        serializer.Serialize(textWriter, new List<MyWrapper>{wrapper});
    }
}

static List<MyWrapper> DeserializeFromXML()
{
    XmlSerializer deserializer = new XmlSerializer(typeof(List<MyWrapper>));
    using (TextReader textReader = File.OpenText("test.xml"))
    {
        return (List<MyWrapper>)deserializer.Deserialize(textReader);
    }
}

または(単一の要素の場合):

static public void SerializeToXML(MyWrapper wrapper)
{
    XmlSerializer serializer = new XmlSerializer(typeof(MyWrapper));
    using (TextWriter textWriter = File.CreateText("test.xml"))
    {
        serializer.Serialize(textWriter, wrapper);
    }
}

static MyWrapper DeserializeFromXML()
{
    XmlSerializer deserializer = new XmlSerializer(typeof(MyWrapper));
    using (TextReader textReader = File.OpenText("test.xml"))
    {
        return (MyWrapper)deserializer.Deserialize(textReader);
    }
}

一貫性を保つ必要がある、それだけです。

于 2010-01-24T21:13:51.887 に答える