I need to store data in this format:

category1 {
"line of text1"
"line of text2"
"line of text3"
...
}
category2 {
"line of text1"
"line of text2"
"line of text3"
...
}
....

I also need to be able to add and delete categorys, and "lines of text". I can't seem to figure out how to do it efficiently in xml files.

using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;

namespace daniweb
{
  public class Categories
  {
    private List<string> _category1;
    private List<string> _category2;

    public List<string> Category1
    {
      get { return _category1; }
      set 
      {
        if (value == null) return;
        _category1 = value; 
      }
    }

    public List<string> Category2
    {
      get { return _category2; }
      set 
      {
        if (value == null) return;
        _category2 = value; 
      }
    }

    public Categories()
    {
      _category1 = new List<string>();
      _category2 = new List<string>();
    }

    public void SaveToFile(string FileName)
    {
      if (File.Exists(FileName))
        File.Delete(FileName);
      XmlSerializer ser = new XmlSerializer(typeof(Categories));
      using (FileStream fs = new FileStream(FileName, FileMode.CreateNew))
      {
        ser.Serialize(fs, this);
      }
    }

    public static Categories LoadFromFile(string FileName)
    {
      XmlSerializer ser = new XmlSerializer(typeof(Categories));
      Categories result;
      using (FileStream fs = new FileStream(FileName, FileMode.Open))
      {
        result = (Categories)ser.Deserialize(fs);
      }
      return result;
    }

  }
}

Calling it:

private void button9_Click(object sender, EventArgs e)
    {
      Categories c = new Categories();
      c.Category1.Add("a");
      c.Category1.Add("b");
      c.Category1.Add("c");
      c.SaveToFile(@"C:\test.xml");
    }

    private void button10_Click(object sender, EventArgs e)
    {
      Categories c = Categories.LoadFromFile(@"C:\test.xml");
      c.Category1.Remove("b");
      c.SaveToFile(@"C:\test.xml");
    }

thanks alot, this is perfect

is there a way to add and delete new categories without creating/deleting a file every time?

correct me if im wrong but doesn't your class only allow 2 categories per file?

You could add however many you wanted... that was just an example. You always rewrite the file so there isn't a big performance hit with I/O if that is your concern. Unless you're appending data to the end of a file then you are effectively erasing it (in 90% of the cases).

Here is an example of a class I serialize with the XmlSerializer :

[Serializable]
  public sealed class ChartConfiguration
  {
    private List<int> _regions;
    private List<int> _facilites;
    private List<int> _servers;
    private List<int> _sensors;
    private DateTime _startDate;
    private DateTime _endDate;
    private RelativeDate _relativeStartDate;
    private RelativeDate _relativeEndDate;
    private List<DateRange> _dateList;
    private List<RelativeDateRange> _relativeDateList;
    private bool _useRelativeDates;
    private bool _useTrendComparison;
    private bool _showMin;
    private bool _showMax;
    private bool _showAvg;
    private bool _showSum;
    private bool _showCount;
    private bool _showAllPoints;
    private bool _useChartTitle;
    private bool _showLegend;
    private string _chartTitle;
    private ChartType _chartType;
    private ServerTreeResolution _serverTreeResolution;
    private DateTimeMeasurementUnit _dateTimeMeasureUnit;
    private List<int> _countGroups;
    private List<ChartDataSource> _chartDataSources;
    private string _chartXml;
    private bool _enableRuntimeHitTesting;
    private bool _enableCacheToMemory;
    private bool _enableScrolling;
    private bool _enableZooming;
    private bool _enableThresholdColor;
    private decimal _lowThreshold;
    private decimal _highThreshold;
    private bool _alwaysShowZeroLevel;
    private bool _hideSeriesWithNoPoints;
    private bool _showThresholdCaptions;
    private bool _useHoursOfOperation;
    private bool _resolveOverlapping;
    private bool _showValueLabel;
    private bool _showValueMarker;
    private List<SeriesTag> _seriesTags;
    private decimal _scaleFactor;
    private DepartmentReportList _departments;
    private bool _limitServerTreeOnSensorType;
    /* -------------------------------------------------------------------- */
    public List<int> Regions
    {
      get { return _regions; }
      set
      {
        if (value == null) return;
        _regions = value;
      }
    }
    public List<int> Facilities
    {
      get { return _facilites; }
      set
      {
        if (value == null) return;
        _facilites = value;
      }
    }
    public List<int> Servers
    {
      get { return _servers; }
      set
      {
        if (value == null) return;
        _servers = value;
      }
    }
    public List<int> Sensors
    {
      get { return _sensors; }
      set
      {
        if (value == null) return;
        _sensors = value;
      }
    }
    public DateTime StartDate
    {
      get { return _startDate; }
      set { _startDate = value; }
    }
    public DateTime EndDate
    {
      get { return _endDate; }
      set { _endDate = value; }
    }
    public RelativeDate RelativeStartDate
    {
      get { return _relativeStartDate; }
      set { _relativeStartDate = value; }
    }
    public RelativeDate RelativeEndDate
    {
      get { return _relativeEndDate; }
      set { _relativeEndDate = value; }
    }
    public List<DateRange> DateList
    {
      get { return _dateList; }
      set
      {
        if (value == null) return;
        _dateList = value;
      }
    }
    public List<RelativeDateRange> RelativeDateList
    {
      get { return _relativeDateList; }
      set
      {
        if (value == null) return;
        _relativeDateList = value;
      }
    }
    public bool UseRelativeDates
    {
      get { return _useRelativeDates; }
      set { _useRelativeDates = value; }
    }
    public bool UseTrendComparison
    {
      get { return _useTrendComparison; }
      set { _useTrendComparison = value; }
    }
    public bool ShowMin
    {
      get { return ((!ShowAllPoints) && _showMin); }
      set { _showMin = value; }
    }
    public bool ShowMax
    {
      get { return ((!ShowAllPoints) && _showMax); }
      set { _showMax = value; }
    }
    public bool ShowAvg
    {
      get { return ((!ShowAllPoints) && _showAvg); }
      set { _showAvg = value; }
    }
    public bool ShowAllPoints
    {
      get { return _showAllPoints; }
      set { _showAllPoints = value; }
    }
    public bool ShowSum
    {
      get { return ((!ShowAllPoints) && _showSum); }
      set { _showSum = value; }
    }
    public bool ShowCount
    {
      get { return _showCount; }
      set { _showCount = value; }
    }
    public bool UseChartTitle
    {
      get { return _useChartTitle; }
      set { _useChartTitle = value; }
    }
    public bool ShowLegend
    {
      get { return _showLegend; }
      set { _showLegend = value; }
    }
    public string ChartTitle
    {
      get { return _chartTitle; }
      //XMLSerializer changes \r\n to \n. We take out the \r and substitue all \n to \r\n.
      set 
      {
        if (value == null)
          _chartTitle = null;
        else
          _chartTitle = value.Replace("\r", string.Empty).Replace("\n", Environment.NewLine); 
      }
    }
    public ChartType ChartType
    {
      get { return _chartType; }
      set { _chartType = value; }
    }
    public ServerTreeResolution ServerTreeResolution
    {
      get { return _serverTreeResolution; }
      set { _serverTreeResolution = value; }
    }
    public DateTimeMeasurementUnit DateTimeMeasureUnit
    {
      get { return _dateTimeMeasureUnit; }
      set { _dateTimeMeasureUnit = value; }
    }
    public List<int> CountGroups
    {
      get { return _countGroups; }
      set
      {
        if (value == null) return;
        _countGroups = value;
      }
    }
    public List<ChartDataSource> ChartDataSources
    {
      get { return _chartDataSources; }
      set { _chartDataSources = value; }
    }
    public string ChartXml
    {
      get { return _chartXml; }
      set { _chartXml = value; }
    }
    public bool EnableRuntimeHitTesting
    {
      get { return _enableRuntimeHitTesting; }
      set { _enableRuntimeHitTesting = value; }
    }
    public bool EnableCacheToMemory
    {
      get { return _enableCacheToMemory; }
      set { _enableCacheToMemory = value; }
    }
    public bool EnableScrolling
    {
      get { return _enableScrolling; }
      set { _enableScrolling = value; }
    }
    public bool EnableZooming
    {
      get { return _enableZooming; }
      set { _enableZooming = value; }
    }
    public bool EnableThresholdColor
    {
      get { return _enableThresholdColor; }
      set { _enableThresholdColor = value; }
    }
    public decimal LowThreshold
    {
      get { return _lowThreshold; }
      set { _lowThreshold = value; }
    }
    public decimal HighThreshold
    {
      get { return _highThreshold; }
      set { _highThreshold = value; }
    }
    public bool AlwaysShowZeroLevel
    {
      get { return _alwaysShowZeroLevel; }
      set { _alwaysShowZeroLevel = value; }
    }
    public bool HideSeriesWithNoPoints
    {
      get { return _hideSeriesWithNoPoints; }
      set { _hideSeriesWithNoPoints = value; }
    }
    public bool ShowThresholdCaptions
    {
      get { return _showThresholdCaptions; }
      set { _showThresholdCaptions = value; }
    }
    public bool UseHoursOfOperation
    {
      get { return _useHoursOfOperation; }
      set { _useHoursOfOperation = value; }
    }
    public bool ResolveOverlapping
    {
      get { return _resolveOverlapping; }
      set { _resolveOverlapping = value; }
    }
    public bool ShowValueLabel
    {
      get { return _showValueLabel; }
      set { _showValueLabel = value; }
    }
    public bool ShowValueMarker
    {
      get { return _showValueMarker; }
      set { _showValueMarker = value; }
    }
    public List<SeriesTag> SeriesTags
    {
      get { return _seriesTags; }
      set { _seriesTags = value; }
    }
    public decimal ScaleFactor
    {
      get { return _scaleFactor; }
      set { _scaleFactor = value; }
    }
    public DepartmentReportList Departments
    {
      get { return _departments; }
      set 
      {
        if (value == null) return;
        _departments = value; 
      }
    }
    public bool LimitServerTreeOnSensorType
    {
      get { return _limitServerTreeOnSensorType; }
      set { _limitServerTreeOnSensorType = value; }
    }
    /* -------------------------------------------------------------------- */
    public ChartConfiguration()
    {
      _regions = new List<int>();
      _facilites = new List<int>();
      _servers = new List<int>();
      _sensors = new List<int>();
      _dateList = new List<DateRange>();
      _relativeDateList = new List<RelativeDateRange>();
      _countGroups = new List<int>();
      _chartDataSources = new List<ChartDataSource>();
      _seriesTags = new List<SeriesTag>();
      _departments = new DepartmentReportList();
      //default values for new fields
      _scaleFactor = 1;
      _limitServerTreeOnSensorType = true;
      _showLegend = true;
    }
    /* -------------------------------------------------------------------- */
    public ChartConfiguration(ChartType chartType)
      : this()
    {
      this.ChartType = chartType;
      SetupChartDefaults();
    }
    /* -------------------------------------------------------------------- */
    private void SetupChartDefaults()
    {
      switch (this.ChartType)
      {
        case ChartType.Traffic:
          this.StartDate = Dates.RelativeDateToAbsolute(RelativeDate.Today);
          this.EndDate = Dates.RelativeDateToAbsolute(RelativeDate.Tomorrow);
          this.ShowMin = false;
          this.ShowMax = false;
          this.ShowAvg = false;
          this.ShowSum = true;
          this.ShowCount = false;
          this.ShowAllPoints = false;
          this.UseChartTitle = true;
          this.ChartTitle = GetDefaultChartTitle();
          this.ServerTreeResolution = ServerTreeResolution.Facility;
          this.DateTimeMeasureUnit = DateTimeMeasurementUnit.Hour;
          this.AlwaysShowZeroLevel = true;
          this.UseHoursOfOperation = true;
          break;
        case ChartType.Temperature:
          this.StartDate = Dates.RelativeDateToAbsolute(RelativeDate.Today);
          this.EndDate = Dates.RelativeDateToAbsolute(RelativeDate.Tomorrow);
          this.ShowMin = false;
          this.ShowMax = false;
          this.ShowAvg = true;
          this.ShowSum = false;
          this.ShowCount = false;
          this.ShowAllPoints = false;
          this.UseChartTitle = true;
          this.ChartTitle = GetDefaultChartTitle();
          this.ServerTreeResolution = ServerTreeResolution.Sensor;
          this.DateTimeMeasureUnit = DateTimeMeasurementUnit.Hour;
          this.AlwaysShowZeroLevel = false;
          this.UseHoursOfOperation = false;
          break;
        case ChartType.Humidity:
          this.StartDate = Dates.RelativeDateToAbsolute(RelativeDate.Today);
          this.EndDate = Dates.RelativeDateToAbsolute(RelativeDate.Tomorrow);
          this.ShowMin = false;
          this.ShowMax = false;
          this.ShowAvg = true;
          this.ShowSum = false;
          this.ShowCount = false;
          this.ShowAllPoints = false;
          this.UseChartTitle = true;
          this.ChartTitle = GetDefaultChartTitle();
          this.ServerTreeResolution = ServerTreeResolution.Sensor;
          this.DateTimeMeasureUnit = DateTimeMeasurementUnit.Hour;
          this.AlwaysShowZeroLevel = true;
          this.UseHoursOfOperation = false;
          break;
        case ChartType.TempHumid:
          this.StartDate = Dates.RelativeDateToAbsolute(RelativeDate.Today);
          this.EndDate = Dates.RelativeDateToAbsolute(RelativeDate.Tomorrow);
          this.ShowMin = false;
          this.ShowMax = false;
          this.ShowAvg = true;
          this.ShowSum = false;
          this.ShowCount = false;
          this.ShowAllPoints = false;
          this.UseChartTitle = true;
          this.ChartTitle = GetDefaultChartTitle();
          this.ServerTreeResolution = ServerTreeResolution.Sensor;
          this.DateTimeMeasureUnit = DateTimeMeasurementUnit.Hour;
          this.AlwaysShowZeroLevel = false;
          this.UseHoursOfOperation = false;
          break;
        case ChartType.Analog:
          this.StartDate = Dates.RelativeDateToAbsolute(RelativeDate.Today);
          this.EndDate = Dates.RelativeDateToAbsolute(RelativeDate.Tomorrow);
          this.ShowMin = false;
          this.ShowMax = false;
          this.ShowAvg = true;
          this.ShowSum = false;
          this.ShowCount = false;
          this.ShowAllPoints = false;
          this.UseChartTitle = true;
          this.ChartTitle = GetDefaultChartTitle();
          this.ServerTreeResolution = ServerTreeResolution.Sensor;
          this.DateTimeMeasureUnit = DateTimeMeasurementUnit.Hour;
          this.AlwaysShowZeroLevel = false;
          this.UseHoursOfOperation = false;
          break;
        case ChartType.Occupancy:
          this.StartDate = Dates.RelativeDateToAbsolute(RelativeDate.Today);
          this.EndDate = Dates.RelativeDateToAbsolute(RelativeDate.Tomorrow);
          this.ShowMin = false;
          this.ShowMax = true;
          this.ShowAvg = true;
          this.ShowSum = false;
          this.ShowCount = false;
          this.ShowAllPoints = false;
          this.UseChartTitle = true;
          this.ChartTitle = GetDefaultChartTitle();
          this.ServerTreeResolution = ServerTreeResolution.Facility;
          this.DateTimeMeasureUnit = DateTimeMeasurementUnit.Hour;
          this.AlwaysShowZeroLevel = true;
          this.UseHoursOfOperation = true;
          break;
        default:
          throw new InvalidOperationException("Unknown chart type");
      }
      this.EnableCacheToMemory = true;
      this.EnableRuntimeHitTesting = false;
      this.EnableScrolling = true;
      this.EnableZooming = true;
      this.HideSeriesWithNoPoints = true;
      this.ShowThresholdCaptions = true;
      this.RelativeStartDate = RelativeDate.Today;
      this.RelativeEndDate = RelativeDate.Tomorrow;
      this.ShowValueMarker = true;
      this.ShowValueLabel = true;
      this.ResolveOverlapping = false;
    }
    /* -------------------------------------------------------------------- */
    private string GetDefaultChartTitle()
    {
      switch (this.ChartType)
      {
        case ChartType.Traffic:
          return string.Format("Traffic Report" + Environment.NewLine +
            "{0} through {1} each {2}",
            TitleVariables.StartDate,
            TitleVariables.EndDate,
            TitleVariables.Measure);
        case ChartType.Temperature:
          return string.Format("Temperature Report" + Environment.NewLine +
            "{0} through {1} each {2}",
            TitleVariables.StartDate,
            TitleVariables.EndDate,
            TitleVariables.Measure);
        case ChartType.Humidity:
          return string.Format("Humidity Report" + Environment.NewLine +
            "{0} through {1} each {2}",
            TitleVariables.StartDate,
            TitleVariables.EndDate,
            TitleVariables.Measure);
        case ChartType.TempHumid:
          return string.Format("Temperature/Humidity Report" + Environment.NewLine +
            "{0:d} through {1} each {2}",
            TitleVariables.StartDate,
            TitleVariables.EndDate,
            TitleVariables.Measure);
        case ChartType.Analog:
          return string.Format("Analog Report" + Environment.NewLine +
            "{0} through {1} each {2}",
            TitleVariables.StartDate,
            TitleVariables.EndDate,
            TitleVariables.Measure);
        case ChartType.Occupancy:
          return string.Format("Occupancy Report" + Environment.NewLine +
            "{0} through {1} each {2}",
            TitleVariables.StartDate,
            TitleVariables.EndDate,
            TitleVariables.Measure);
        default:
          throw new InvalidOperationException("Unknown Chart Type");
      }
    }
    /* -------------------------------------------------------------------- */
    public string GetSubstitutedChartTitle(string title)
    {
      List<DateRange> lst = GetDateRanges();
      DateRange range;

      if (lst.Count > 0)
        range = lst[0];
      else
        range = new DateRange(System.Data.SqlTypes.SqlDateTime.MinValue.Value, System.Data.SqlTypes.SqlDateTime.MaxValue.Value);

      string result = title;

      result = result.Replace(TitleVariables.StartDate, range.StartDate.Date.ToString("d"));
      result = result.Replace(TitleVariables.EndDate, range.EndDate.Date.ToString("d"));
      result = result.Replace(TitleVariables.Measure, DateTimeMeasureUnit.ToString());

      return result;
    }
    /* -------------------------------------------------------------------- */
    public List<DateRange> GetDateRanges()
    {
      List<DateRange> result = new List<DateRange>();
      if (UseRelativeDates)
      {
        //Relative Dates
        if (UseTrendComparison)
        {
          foreach (RelativeDateRange range in this.RelativeDateList)
          {
            DateRange dr = new DateRange();
            dr.StartDate = Dates.RelativeDateToAbsolute(range.StartDate);
            dr.EndDate = Dates.RelativeDateToAbsolute(range.EndDate);
            result.Add(dr);
          }
        }
        else
        {
          DateRange dr = new DateRange();
          dr.StartDate = Dates.RelativeDateToAbsolute(this.RelativeStartDate);
          dr.EndDate = Dates.RelativeDateToAbsolute(this.RelativeEndDate);
          result.Add(dr);
        }
      }
      else
      {
        //Absolute Dates
        if (UseTrendComparison)
        {
          result.AddRange(this.DateList);
        }
        else
        {
          DateRange dr = new DateRange();
          dr.StartDate = this.StartDate;
          dr.EndDate = this.EndDate;
          result.Add(dr);
        }
      }
      return result;
    }
    /* -------------------------------------------------------------------- */
    public static class TitleVariables
    {
      [
      NonSerialized,
      XmlIgnore
      ]
      public const string StartDate = @"%BeginDate%";
      [
      NonSerialized,
      XmlIgnore
      ]
      public const string EndDate = @"%EndDate%";
      [
      NonSerialized,
      XmlIgnore
      ]
      public const string Measure = @"%Measure%";
    }
    /* -------------------------------------------------------------------- */
    public SeriesTag FindTag(string SeriesGUID)
    {
      if (string.IsNullOrEmpty(SeriesGUID))
        return null;

      foreach (SeriesTag tag in this.SeriesTags)
      {
        if (string.Compare(tag.SeriesGUID, SeriesGUID, true) == 0)
          return tag;
      }
      return null;
    }
    /* -------------------------------------------------------------------- */
  }

You can serialize just about anything you want :)

Comments
Great code by the great poster.
This article has been dead for over six months. Start a new discussion instead.