cbutler
cbutler

Reputation: 943

C# append object to xml file using serialization

I am trying append a serialized object to an existing xml file beneath the root element, which I thought would be simple but is proving to be a little challenging.

The problem is in the AddShortcut method but I added some more code for completeness.

I believe what I need to do is:

  1. load the file into an XmlDocument.
  2. navigate to the node I want to append beneath (here the node name is Shortcuts).
  3. create some type of writer and then serialize the object.
  4. save the XmlDocument.

The trouble is in steps 2 and 3. I have tried different variations but I think using XPathNavigator somehow to find the "root" node to append under is a step in the right direction.

I have also looked at almost every question on Stack Overflow on the subject.

Any suggestions welcome. Here is my code

class XmlEngine
{
   public string FullPath { get; set; } // the full path to the xmlDocument
   private readonly XmlDocument xDoc; 

   public XmlEngine(string fullPath, string startElement, string[] rElements)
   {
      FullPath = fullPath;
      xDoc = new XmlDocument();
      CreateXmlFile(FullPath, startElement, rElements);            
   }

   public void CreateXmlFile(string path, string startElement, string[] rElements)
   {
     try
     {
       if (!File.Exists(path))
       {
         // create a txt writer
         XmlTextWriter wtr = new XmlTextWriter(path, System.Text.Encoding.UTF8);

         // make sure the file is well formatted
         wtr.Formatting = Formatting.Indented;

         wtr.WriteProcessingInstruction("xml", "version='1.0' encoding='UTF-8'");
         wtr.WriteStartElement(startElement);
         wtr.Close();

         // write the top level root elements
         writeRootElements(path, rElements);
       }
     }
     catch (Exception ex)
     {
       Console.WriteLine("Error: " + ex.Message);
       Console.WriteLine("Could not create file: " + path);
     }
  }

  public void AddShortcut(Shortcut s)
  {
     xDoc.Load(FullPath);
     rootNode = xDoc.AppendChild(xDoc.CreateElement("Shortcuts"));

     var serializer = new XmlSerializer(s.GetType());

     using (var writer = new StreamWriter(FullPath, true))
     {
        XmlWriterSettings ws = new XmlWriterSettings();
        ws.OmitXmlDeclaration = true;

        serializer.Serialize(writer, s);
     }

     xDoc.Save(FullPath);

  }

}

Upvotes: 2

Views: 10386

Answers (2)

cbutler
cbutler

Reputation: 943

This code sample worked for me:

xml:

<?xml version="1.0" encoding="UTF-8"?>
<Launchpad>
  <Shortcuts>
    <Shortcut Id="1">
      <Type>Folder</Type>
      <FullPath>C:\SomePath</FullPath>
      <Name>SomeFolderName</Name>
    </Shortcut>   
  </Shortcuts>
</Launchpad>

Method:

public void AddShortcut(Shortcut s)
{
   xDoc.Load(FullPath);
   var rootNode = xDoc.GetElementsByTagName("Shortcuts")[0];
   var nav = rootNode.CreateNavigator();
   var emptyNamepsaces = new XmlSerializerNamespaces(new[] {
       XmlQualifiedName.Empty
   });

   using (var writer = nav.AppendChild())
   {
      var serializer = new XmlSerializer(s.GetType());
      writer.WriteWhitespace("");
      serializer.Serialize(writer, s, emptyNamepsaces);
      writer.Close();
   }            
   xDoc.Save(FullPath);
}

Upvotes: 3

user270576
user270576

Reputation: 997

  1. load the file into an XmlDocument.
  2. navigate to the node I want to append beneath (here the node name is Shortcuts).
  3. create some type of writer and then serialize the object.
  4. save the XmlDocument

So:

public void AddShortcut(Shortcut s)
{
    // 1. load existing xml
    xDoc.Load(FullPath);
    // 2. create an XML node from object
    XmlElement node = SerializeToXmlElement(s);
    // 3. append that node to Shortcuts node under XML root
    var shortcutsNode = xDoc.CreateElement("Shortcuts")
    shortcutsNode.AppendChild(node);
    xDoc.DocumentElement.AppendChild(shortcutsNode);
    // 4. save changes
    xDoc.Save(FullPath);
}

public static XmlElement SerializeToXmlElement(object o)
{
    XmlDocument doc = new XmlDocument();
    using(XmlWriter writer = doc.CreateNavigator().AppendChild())
    {
        new XmlSerializer(o.GetType()).Serialize(writer, o);
    }
    return doc.DocumentElement;
}

This post

Upvotes: 0

Related Questions