【问题标题】:XML - Can not deserialize after serializeXML - 序列化后无法反序列化
【发布时间】:2013-10-10 00:26:41
【问题描述】:

我创建了一个列表,将其保存为 XML(使用 XmlSerializer),但我没有成功(尽管所有网络搜索......)来反序列化。

我的实体是:

public class basicTxtFile
{
    public string filename;
    public string description;
}

public class fileTools
{
};

public class textboxTool : fileTools    // text box
{
    public string defaultText;
    public bool multiLine;
    public bool browseButton;
};

public class comboboxTool : fileTools   // combo box
{
    public List<string> values = new List<string>();
};

// Must file, can choose tools: textbox and\or combobox
public class mustFiles : basicTxtFile
{
    public List<fileTools> mustTools = new List<fileTools>();
};

public class OptionalFiles : mustFiles
{
    public bool exist;  // checkbox for defualt value - if the file is exist, if not.
};

在我的应用程序中,我创建了一个列表并手动填写它。 之后我用这段代码保存了它:

//  Save list into XML  -   success
XmlSerializer serializer = new XmlSerializer(typeof(List<mustFiles>), new Type[] {typeof(fileTools), typeof(textboxTool), typeof(comboboxTool)});

using (FileStream stream = File.OpenWrite("MustFiles.xml"))
{
    serializer.Serialize(stream, mustTxtFiles);
}

然后我尝试将 xml 文件加载到列表中,但由于:“XML 文档 (2, 2) 中存在错误。” 和 _innerException = "没想到。” 虽然xml文件是自动生成的。

我的加载代码是:

// Load XML file into list
List<mustFiles> mustTry = new List<mustFiles>();
mustTry = bl.loadXmlIntoList<mustFiles>("MustFiles.xml", "mustFiles");

loadXmlIntoList 函数:

public List<T> loadXmlIntoList<T>(string xmlFileName, string xmlElemnetName)
{
    XmlRootAttribute xRoot = new XmlRootAttribute();
    xRoot.ElementName = xmlElemnetName;
    xRoot.IsNullable = true;

    XmlSerializer serializer = new XmlSerializer(typeof(T), xRoot);

    using (FileStream stream = File.OpenRead(xmlFileName))
    {
        List<T> dezerializedList = (List<T>)serializer.Deserialize(stream);
        return dezerializedList;
    }
}

我的问题:我做错了什么?如何将 xml 文件加载到列表中?

谢谢!

XML 文件(自动生成)如下所示:

<?xml version="1.0"?>
<ArrayOfMustFiles xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <mustFiles>
    <filename>file1.txt</filename>
    <description>desc1</description>
    <mustTools>
      <fileTools xsi:type="textboxTool">
        <defaultText>Default text 01</defaultText>
        <multiLine>false</multiLine>
        <browseButton>false</browseButton>
      </fileTools>
    </mustTools>
  </mustFiles>
  <mustFiles>
    <filename>file2.txt</filename>
    <description>desc2</description>
    <mustTools>
      <fileTools xsi:type="textboxTool">
        <defaultText>Defualt text 02</defaultText>
        <multiLine>true</multiLine>
        <browseButton>true</browseButton>
      </fileTools>
      <fileTools xsi:type="comboboxTool">
        <values>
          <string>Val1</string>
          <string>Val2</string>
          <string>Val3</string>
        </values>
      </fileTools>
    </mustTools>
  </mustFiles>
  <mustFiles>
    <filename>file2.txt</filename>
    <description>desc2</description>
    <mustTools>
      <fileTools xsi:type="textboxTool">
        <defaultText>Defualt text 03</defaultText>
        <multiLine>false</multiLine>
        <browseButton>true</browseButton>
      </fileTools>
      <fileTools xsi:type="comboboxTool">
        <values>
          <string>ComboVal 1</string>
          <string>ComboVal  2</string>
          <string>ComboVal  3</string>
        </values>
      </fileTools>
      <fileTools xsi:type="comboboxTool">
        <values>
          <string>Second ComboVal 1</string>
          <string>Second ComboVal  2</string>
          <string>Second ComboVal  3</string>
        </values>
      </fileTools>
      <fileTools xsi:type="textboxTool">
        <defaultText>Second defualt text 03</defaultText>
        <multiLine>true</multiLine>
        <browseButton>false</browseButton>
      </fileTools>
    </mustTools>
  </mustFiles>
</ArrayOfMustFiles>

更新:我也尝试将{get; set;} 添加到实体中,如下所示:

public class basicTxtFile
{
    public string filename{ set; get; }
    public string description{ set; get; }
}

public class fileTools
{ };

public class textboxTool : fileTools
{
    public string defaultText{ set; get; }
    public bool multiLine{ set; get; }
    public bool browseButton{ set; get; }
};

public class comboboxTool : fileTools
{
    public List<string> values { set; get; }
    public comboboxTool()
    {
        values = new List<string>();
    }
};

public class mustFiles : basicTxtFile
{
    public List<fileTools> mustTools { set; get; }
    public mustFiles()
    {
        mustTools = new List<fileTools>();
    }
};

【问题讨论】:

  • 我没有看到对 Deserialize() 的调用。什么是 loadXmlIntoList()?
  • 对不起,我忘记换了。我现在将更新我的问题。谢谢
  • 添加功能。再次感谢

标签: c# xml xml-serialization xml-deserialization


【解决方案1】:

我不是 XML 专家。你想用 loadXmlIntoList() 中的 XmlRootAttribute 做什么?

我对其进行了轻微修改,使反序列化代码看起来更像它的序列化对应物:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        List<mustFiles> mustTxtFiles = new List<mustFiles>();

        mustFiles mf = new mustFiles();
        mf.filename = "filenameA";
        mf.description = "descriptionA";
        textboxTool tbt = new textboxTool();
        tbt.defaultText = "defaultTextA";
        tbt.browseButton = true;
        tbt.multiLine = true;
        mf.mustTools.Add(tbt);
        mustTxtFiles.Add(mf);

        mf = new mustFiles();
        mf.filename = "filenameB";
        mf.description = "descriptionB";
        tbt = new textboxTool();
        tbt.defaultText = "defaultTextB";
        tbt.browseButton = true;
        tbt.multiLine = true;
        mf.mustTools.Add(tbt);
        mustTxtFiles.Add(mf);

        // serialize it
        XmlSerializer serializer = new XmlSerializer(typeof(List<mustFiles>), new Type[] {typeof(fileTools), typeof(textboxTool), typeof(comboboxTool)});
        string xmlFile = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MustFiles.xml");
        using (System.IO.FileStream stream = File.OpenWrite(xmlFile))
        {
            serializer.Serialize(stream, mustTxtFiles);
        }

        // Why not just this?
        // deserialize it 
        //List<mustFiles> mustTry;
        //using (FileStream stream = File.OpenRead(xmlFile))
        //{
        //    mustTry = (List<mustFiles>)serializer.Deserialize(stream);
        //}

        // deserialize it with generic function:
        List<mustFiles> mustTry = loadXml<List<mustFiles>>(xmlFile, new Type[] { typeof(fileTools), typeof(textboxTool), typeof(comboboxTool) });
    }

    public T loadXml<T>(string xmlFileName, Type[] additionalTypes)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(T), additionalTypes);
        using (FileStream stream = File.OpenRead(xmlFileName))
        {
            return (T)serializer.Deserialize(stream);
        }
    }

}

【讨论】:

    【解决方案2】:

    我认为您的原因是缺少您正在序列化或反序列化的属性的 get{} set{} 方法!

    如果要在序列化中使用它们,则必须将其用作属性。如果您仅将它们用作没有 get & set 的字段,则会出现问题

    【讨论】:

    • 我加了{get; set;},但还是不行。你能解释一下你在use it as properties中的意思吗?谢谢。
    • 在你的代码中你写了 public class basicTxtFile { public string filename;公共字符串描述;如果您改用此上下文中的变量,则 FIELDS 不能用作封装属性: public class basicTxtFile { public string filename { get;放; };公共字符串描述{获取;放; };这使得字段成为封装属性!通常它现在应该与序列化程序一起使用
    • 你必须添加get;放;到 ALLE 用于 XML 元素的元素
    • 我尝试添加 {get; set;} 但它仍然不起作用。我将使用 {get; 将版本添加到问题中。设置;} 现在。谢谢
    • @Sven 根据此 MSDN 文档,您不需要它们:msdn.microsoft.com/en-us/library/aa302290.aspx 向下滚动,它们不使用单个 get{} 或 get; 或 set{} 或 set;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-12
    • 1970-01-01
    • 2019-09-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多