Pregunta

I create a list, save it as XML (with XmlSerializer) but I not success (although all web searches…) to deserialize.

My entities are:

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.
};

In my application I crate a list and I fill it manually. After it I saved it with this code:

//  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);
}

Then I try to load the xml file into list, but it's failed due to: "There is an error in XML document (2, 2)." and _innerException = " was not expected." although the xml file generate automatically.

My load code is:

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

loadXmlIntoList function:

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;
    }
}

My question: What I did wrong? how can I load the xml file into the list?

Thank you!

The XML file (that generate automatically) looks like this:

<?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>

Update: I also try add {get; set;} to The entities, like this:

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>();
    }
};
¿Fue útil?

Solución

I'm not an XML expert. What are you trying to do with the XmlRootAttribute in loadXmlIntoList()?

I've reworked it slightly so that the deserialization code looks more like its serialization counterpart:

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);
        }
    }

}

Otros consejos

I think your is caused while missing the get{} set{} methods of the properties you are serializing or deserializing!

You have to use it as properties if you want to use them in serialization. there are Problems if you use them only as fields without get & set

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top