4

I have an existing XML file that I would like to append without changing the format. Existing File looks like this:

<Clients>
  <User username="farstucker">
    <UserID>1</UserID>
    <DOB />
    <FirstName>Steve</FirstName>
    <LastName>Lawrence</LastName>
    <Location>NYC</Location>
  </User>
</Clients>

How can I add another user using this format? My existing code is:

        string fileLocation = "clients.xml";

        XmlTextWriter writer;

        if (!File.Exists(fileLocation))
        {
            writer = new XmlTextWriter(fileLocation, null);
            writer.WriteStartDocument();

            // Write the Root Element
            writer.WriteStartElement("Clients");

            // End Element and Close
            writer.WriteEndElement();
            writer.Close();
        }
// Append new data here

Ive thought about using XmlDocument Fragment to append the data but Im not certain if I can maintain the existing format ( and empty tags ) without messing up the file.

Any advice you could give is much appreciated.

EDIT Ive changed the code to read the original XML but the file keeps getting overwritten.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Ryan
  • 4,443
  • 4
  • 26
  • 26

3 Answers3

5

You should use the XmlDocument class to load the whole file, modify it in memory and then write the contents back replacing the original file. Don't worry, it won't mess up your markup, and you can even ask it to preserve non-significant whitespace in the original document using the PreserveWhitespace property (http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.preservewhitespace.aspx).

kicsit
  • 291
  • 1
  • 2
  • 3
    I agree with what kicsit says except for the part where he says "XmlDocument", you want to use XDocument and Linq to XML as it is significantly nicer and easier to work with. There's a static load method to read the doc from file and an equivalent save. – Murph Apr 15 '10 at 13:15
  • I believe most of the question do not state what version of .NET they are using. LINQ doesn't exist in 2.0 or previous versions. – Nayan Apr 15 '10 at 13:20
1

You could try something like this...

        string fileLocation = "clients.xml";

        if (!File.Exists(fileLocation))
        {
            XmlTextWriter writer = new XmlTextWriter( fileLocation, null );
            writer.WriteStartElement( "Clients" );
            writer.WriteEndElement();
            writer.Close();
        }

        // Load existing clients and add new 
        XElement xml = XElement.Load(fileLocation);
            xml.Add(new XElement("User",
            new XAttribute("username", loginName),
            new XElement("DOB", dob),
            new XElement("FirstName", firstName),
            new XElement("LastName", lastName),
            new XElement("Location", location)));
        xml.Save(fileLocation);

That should get you started, just replace the variables with whatever you are using and dont forget to add the System.Xml.Linq namespace.

If youre still having problems post back here and well help you get through it.

Leroy Jenkins
  • 2,680
  • 6
  • 25
  • 33
0

If you want to use serialization (meaning you have a data object want to serialize in to XML and append to an existing XML file) you can use this generic method SerializeAppend<T>. It does exactly what you need. I also added two more methods for anyone that may benefit

public static void Serialize<T>(T obj, string path)
{
    var writer = new XmlSerializer(typeof(T));

    using (var file = new StreamWriter(path))
    {
        writer.Serialize(file, obj);
    }
}


public static T Deserialize<T>(string path)
{
    var reader = new XmlSerializer(typeof(T));
    using (var stream = new StreamReader(path))
    {
        return (T)reader.Deserialize(stream);
    }

}

public static void SerializeAppend<T>(T obj, string path)
{
    var writer = new XmlSerializer(typeof(T));

    FileStream file = File.Open(path, FileMode.Append, FileAccess.Write);

    writer.Serialize(file, obj);

    file.Close();
}
nhahtdh
  • 55,989
  • 15
  • 126
  • 162
  • with this it will append with the same namespace again.. it wont append to the last child node but it would only append to the document end – ECie May 19 '15 at 01:23