0

I've created an ObservableCollection of type string which contains loaded <Subject> strings from XML file. After adding few strings to Collection by TextBox I want to save updated state of that Collection to an XML file again. I would like each string to have a specific tag, just like this below:

<?xml version="1.0" encoding="utf-8"?>
<Subjects>
 <Subject>One</Subject>
 <Subject>Two</Subject>
 <Subject>Three</Subject>
</Subjects>

I would like to have <Subjects> root and each string in that Collection to have <Subject> child.

I've tried this:

namespace StudyNotes
{
    public class LocalData
    {
        public ObservableCollection<string> Subjects;

        public LocalData()
        {
            Subjects = new ObservableCollection<string>();
            LoadXmlData();
        }

        private void LoadXmlData()
        {
           XmlDocument xmlDocument = new XmlDocument();
           XmlNodeList xmlNodeList;
           using (FileStream fs = new FileStream(startupPath, FileMode.Open, FileAccess.Read))
           {
               xmlDocument.Load(fs);
               xmlNodeList = xmlDocument.GetElementsByTagName("Subject");
               foreach (XmlNode item in xmlNodeList)
               {
                   Subjects.Add(item.InnerText);
               }
               fs.Close();
            }
        }

        public void SaveXmlData()
        {   
            Subjects.Add(TextBox.Text);

            var serializer = new XmlSerializer(typeof(ObservableCollection<string>));

            using (var stream = File.Open(xmlPath, FileMode.Create))
            {
                serializer.Serialize(stream, Subjects);
                stream.Close();
            }
        }
    }
}

Loading data from XML works well, it adds items to ObservableCollection from XML, but problem is in saving data. It doesn't create another node to XML with <Subject> tag, but <string> tag instead and unnecessary <ArrayOfString> tag instead of <Subjects>.

<?xml version="1.0"?>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <string>One</string>
  <string>Two</string>
  <string>Three</string>
</ArrayOfString>

What needs to be done, to add nodes/childs with specific tag from ObservableCollection to XML file?

Sisimośki
  • 143
  • 1
  • 10
  • 1
    `XmlArrayAttribute` and `XmlArrayItemAttribute` are probably what you need. – willaien May 03 '19 at 19:49
  • 2
    Those attributes will work if you put them on the `Subjects` property of `LocalData`, and then serialize the instance of `LocalData`. The root element will be ``, and you can have Subjects be `...` under that. However if you're *just* serializing the ObservableCollection, there's nothing to put the attributes on. The attributes belong to the `LocalData` type, not to the value of the property. So you may just have to write some code to build a stubby little Subjects/Subject XML tree with the appropriate element names, and then use its OuterXml property. – 15ee8f99-57ff-4f92-890c-b56153 May 03 '19 at 19:59
  • Your options would be to 1) Replace the `ObservableCollection` with some appropriate set of DTOs as shown in [Is it possible to deserialize XML into `List`?](https://stackoverflow.com/a/608181/3744182), or 2) Use `XmlAttributeOverrides` as shown in [Constructor of a XmlSerializer serializing a List throws an InvalidOperationException when used with XmlAttributeOverrides](https://stackoverflow.com/a/47129534/3744182), using `typeof(ObservableCollection)` instead of `typeof(List)`. – dbc May 04 '19 at 05:16

0 Answers0