0

I'm trying to serialize an object to and from an XML settings file using XmlSerializer and XmlWriter/XMLReader.

In its simplest form this is fairly trivial:

XmlSerializer oSerializer = new XmlSerializer(typeof(mySettings), new XmlRootAttribute("Settings"));
    using (XmlWriter oXmlWriter = XmlWriter.Create(myFilePath) 
        oSerializer.Serialize(oXmlWriter, mySettings);

and

XmlSerializer oSerializer = new XmlSerializer(typeof(mySettings), new XmlRootAttribute("Settings"));
    using (XmlReader oXmlReader = XmlReader.Create(myFilePath)
        oSerializer.Serialize(oXmlWriter, mySettings);

produces and reads (simplified example):

<?xml version="1.0" encoding="utf-8"?>
<Settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Token>NC05MWY4NmJkOGRl</Token>
  <TokenExpiry>2017-11-01</TokenExpiry>
  <TokenType>bearer</TokenType>
</Settings>

However, I’m trying to save (and read) various versions of the (same) object in different nodes, something like:

<?xml version="1.0" encoding="utf-8"?>
<Settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ThisSetting>
    <Token>NC05MWY4NmJkOGRl</Token>
    <TokenExpiry>2017-11-01</TokenExpiry>
    <TokenType>bearer</TokenType>
  </ThisSetting>
  <ThatSetting>
    <Token>eyJ0eXAiOiJKV1Qi</Token>
    <TokenExpiry>2017-11-05</TokenExpiry>
    <TokenType>token</TokenType>
  </ThatSetting>
</Settings>

NOTE: As the same class of object is being written, the XML structure is identical between nodes.

I can manually describe ThisSetting and ThatSetting; they aren't part of the object definition. And I need to handle the situation where the file doesn't initially exist, or if there is only, say, a ThatSetting when I go to save a ThisSetting (the order in the file is irrelevant), so the ability to add nodes is required. (I could simply have multiple files, I guess, but that seems pretty untidy.)

Can anyone provide a simple and clean way of doing this? Obviously, I can manually parse the file for writing and reading, but that seems like it shouldn't be necessary. And I could wrap the object to provide ThisSetting and ThatSetting as enclosing properties, but ThisSetting and ThatSetting are dynamic according to product names which can vary in name and number and may change over time.

Ideas? Have I missed something obvious?

SteveCinq
  • 1,920
  • 1
  • 17
  • 22
  • Shouldn't the Opening and Closing Tags be written similar: ``? – Nikolaus Nov 18 '17 at 21:39
  • Do you want to save into a File(XML) or a Database? – Nikolaus Nov 18 '17 at 21:39
  • @Nikolaus Typo, sorry. Fixed. To a file, eg settings.xml, as per post. – SteveCinq Nov 18 '17 at 21:41
  • Do Settings always have the same structure? – Nikolaus Nov 18 '17 at 21:43
  • @Nikolaus Yes, as per example and additional note in post. – SteveCinq Nov 18 '17 at 21:48
  • You could load your XML into an `XDocument` (or create one if the file does not exist yet) and then serialize directly to some nested element by following the instructions from [Serialize object to XML WITHIN a parent element](https://stackoverflow.com/q/37443397/3744182). – dbc Nov 18 '17 at 22:01
  • Or, if you're looking for a trick to add a node to an XML file without loading the entire file, see [Fastest way to add new node to end of an xml?](https://stackoverflow.com/q/849043/3744182) for some possibilities. – dbc Nov 18 '17 at 22:15

1 Answers1

0

Easy to do with xml linq :

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


namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            XElement settings = doc.Root;

            List<XElement> children = settings.Elements().ToList();

            settings.Descendants().Remove();

            settings.Add(new XElement("ThisSettings", children));
        }
    }
}
jdweng
  • 33,250
  • 2
  • 15
  • 20