Xml反序列化缺少的字符串

时间:2017-03-29 01:02:26

标签: c# xml serialization

我从xml反序列化一个对象,但KeywordList和ResponseList中的字符串总是空的。

尝试了很多事情,似乎无法做到正确。如果我使用阅读器循环播放,则显示值。

from tkinter import *

def activateMotors():
    if motorsOn.get() == 1:
        scale.config(state=ACTIVE)
    elif motorsOn.get() == 0:
        scale.config(state=DISABLED)


root = Tk()
root.wm_title('Servo Control')
motorsOn= IntVar()
motorsCheck=Checkbutton(root, 
    text="Motors ON(checked)/OFF(unchecked)", 
    variable=motorsOn, 
    command=activateMotors)
motorsCheck.pack()

scale = Scale(root, from_=0, to=180, 
              orient=HORIZONTAL,label="Motor #",state=DISABLED)
scale.pack()
root.mainloop()

以下是示例xml

using System;
using System.Collections.Specialized;
using System.Xml;
using System.Xml.Serialization;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(ElizaResponses));
            using (XmlReader reader = XmlReader.Create("eliza.xml"))
            {
                ElizaResponses responses = (ElizaResponses)serializer.Deserialize(reader);
                reader.Close();

                // This reads in all data
                //StreamReader reader = new StreamReader("eliza.xml");
                //reader.ReadToEnd();
                //reader.MoveToContent();
                //while (reader.Read())
                //{
                //    if(reader.NodeType == XmlNodeType.Text)
                //    {
                //        Console.WriteLine("{0}, {1}", reader.NodeType, reader.Value);
                //    }
                //    else
                //    { 
                //    Console.WriteLine("{0}, {1}", reader.NodeType, reader.Name);
                //    }
                //}


            }

            Console.ReadLine();
        }
    }

    [Serializable]
    [XmlRoot("ElizaResponses")]
    [XmlType("ElizaResponses")]
    public sealed class ElizaResponses
    {
        ElizaConversation[] chatList;

        public ElizaConversation[] ChatList
        {
            get { return this.chatList; }
            set { this.chatList = value; }
        }
    }

    [Serializable]
    public sealed class ElizaConversation
    {
        // Tried List<string>, string[], StringCollection
        StringCollection keywordList = new StringCollection();
        StringCollection responseList = new StringCollection();

        // Tried [XmlArray], [XmlElement]
        [XmlElement("KeywordList")]
        [XmlArrayItem("string", typeof(string))]
        StringCollection KeywordList
        {
            get { return this.keywordList; }
            set { this.keywordList = value; }
        }

        [XmlArray("ResponseList")]
        [XmlArrayItem("string", typeof(string))]
        StringCollection ResponseList
        {
            get { return this.responseList; }
            set { this.responseList = value; }
        }
    }
}

应该添加我没有异常并且已经在app.config文件中显示错误消息

<?xml version="1.0" encoding="utf-8"?>
<ElizaResponses>
  <ChatList>
    <ElizaConversation>
      <KeywordList>
        <string>ok</string>
      </KeywordList>
      <ResponseList>
        <string>cool.</string>
        <string>great.</string>
        <string>:)</string>
      </ResponseList>
    </ElizaConversation>
    <ElizaConversation>
      <KeywordList>
        <string>shutup</string>
        <string>shut up</string>
      </KeywordList>
      <ResponseList>
        <string>make me.</string>
        <string>no I won't.</string>
      </ResponseList>
    </ElizaConversation>
  </ChatList>
</ElizaResponses>

2 个答案:

答案 0 :(得分:1)

您应该首先自动生成它们并验证自动生成的类型是否有效,而不是继续尝试手动生成类型。只有这样,根据需要简化。如果将XML发布到https://xmltocsharp.azurewebsites.net/,则可以生成将反序列化XML的类:

[XmlRoot(ElementName = "KeywordList")]
public class KeywordList
{
    [XmlElement(ElementName = "string")]
    public List<string> String { get; set; }
}

[XmlRoot(ElementName = "ResponseList")]
public class ResponseList
{
    [XmlElement(ElementName = "string")]
    public List<string> String { get; set; }
}

[XmlRoot(ElementName = "ElizaConversation")]
public class ElizaConversation
{
    [XmlElement(ElementName = "KeywordList")]
    public KeywordList KeywordList { get; set; }
    [XmlElement(ElementName = "ResponseList")]
    public ResponseList ResponseList { get; set; }
}

[XmlRoot(ElementName = "ChatList")]
public class ChatList
{
    [XmlElement(ElementName = "ElizaConversation")]
    public List<ElizaConversation> ElizaConversation { get; set; }
}

[XmlRoot(ElementName = "ElizaResponses")]
public class ElizaResponses
{
    [XmlElement(ElementName = "ChatList")]
    public ChatList ChatList { get; set; }
}

您可以使用上面的代码验证此版本的ElizaResponses将反序列化您的XML。但是,这些可以简化。

首先,将KeywordListResponseList合并到StringList

public class StringList
{
    [XmlElement(ElementName = "string")]
    public List<string> String { get; set; }
}

[XmlRoot(ElementName = "ElizaConversation")]
public class ElizaConversation
{
    [XmlElement(ElementName = "KeywordList")]
    public StringList KeywordList { get; set; }
    [XmlElement(ElementName = "ResponseList")]
    public StringList ResponseList { get; set; }
}

接下来,取消StringList完全将其替换为List<string<>。由于消除了额外级别的容器类,因此需要用[XmlElement][XmlArray]替换两个[XmlArrayItem]属性,从而产生以下最终版本:

[XmlRoot(ElementName = "ElizaConversation")]
public class ElizaConversation
{
    [XmlArray(ElementName = "KeywordList")]
    [XmlArrayItem(ElementName = "string")]
    public List<string> KeywordList { get; set; }
    [XmlArray(ElementName = "ResponseList")]
    [XmlArrayItem(ElementName = "string")]
    public List<string> ResponseList { get; set; }
}

[XmlRoot(ElementName = "ChatList")]
public class ChatList
{
    [XmlElement(ElementName = "ElizaConversation")]
    public List<ElizaConversation> ElizaConversation { get; set; }
}

[XmlRoot(ElementName = "ElizaResponses")]
public class ElizaResponses
{
    [XmlElement(ElementName = "ChatList")]
    public ChatList ChatList { get; set; }
}

您最初的尝试包括以下问题:

  • 应避免使用非通用的,过时的StringCollection
  • [XmlArrayItem("Item", typeof(string))]声明中,名称"Item"错误。应该是"string"
  • [XmlElement]无法与[XmlArrayItem]合并。
  • 属性KeywordListResponseList不公开。 XmlSerializer仅序列化公众成员。

示例fiddle

答案 1 :(得分:0)

找到答案。无法设置属性,因为它们不公开。