简体   繁体   中英

Serialized, Deserialized, Append, Get, Delete Object in XML file C#

I have the following class

[Serializable]
public class Product
{
    public Product() { }
    public string ProductID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

I want to create a XML file from object. if the product id exist, update the node other wise add or append the node in xml file.

i am using the following code to serialize object

public void SerializeNode(object obj, string filepath)
{
    XmlSerializer serializer = new XmlSerializer(obj.GetType());
    var writer = new StreamWriter(filepath);
    serializer.Serialize(writer.BaseStream, obj);
}

but it create the file every time from scratch so if the data exist in the file it overwites it with new one.

so i am in search of mechanism where it add/append node in xml, get the node based on ProductID and delete the node.

The class can be extended with more data members so the code should be dynamic so i don't have to specify child elements in code, i want it only in class level.

hope some one can help

the structure i am looking for is as follow

<?xml version="1.0" encoding="utf-8"?>
<Products>
  <Product ProductID="1">
    <Name>Product Name</Name>
   <Description>Product Description</Description>
  </Product>
  <Product ProductID="2">
    <Name>Product Name</Name>
   <Description>Product Description</Description>
  </Product>
  <Product ProductID="3">
    <Name>Product Name</Name>
   <Description>Product Description</Description>
  </Product>
</Products>

I don't get the problem:

  1. deserialize xml to an objext
  2. make changes to object
  3. serialize updated object

Should get you started in a better direction; namely manually serializing with XElement

var elmtProducts = new XElement("Products");

foreach(var item in ProductsList)
{
    var elmtProduct = new XElement("Product");

    elmtProduct.Add(new XElement("Name", "Product Name"));
    elmtProduct.Add(new XElement("Description", "Product Description"));

    //if(
    elmtProducts.Add(elmtProduct);
}

elmtProducts.Save(new FileStream("blah"));

Now, you should be able to work out how to deserialise this. You may as well just load the entire thing back into memory and update with new products and then re-save. If you have so many products that you can't do this, then you need a database, rather than XML.

Here, in case you're not sure how to deserialize, you can do this:

internal class Program
    {
        private static void Main(string[] args)
        {
            //var products = new ProductCollection();
            //products.Add(new Product { ID = 1, Name = "Product1", Description = "This is product 1" });
            //products.Add(new Product { ID = 2, Name = "Product2", Description = "This is product 2" });
            //products.Add(new Product { ID = 3, Name = "Product3", Description = "This is product 3" });
            //products.Save("C:\\Test.xml");

            var products = ProductCollection.Load("C:\\Test.xml");

            Console.ReadLine();
        }
    }

    [XmlRoot("Products")]
    public class ProductCollection : List<Product>
    {
        public static ProductCollection Load(string fileName)
        {
            return new FileInfo(fileName).XmlDeserialize<ProductCollection>();
        }

        public void Save(string fileName)
        {
            this.XmlSerialize(fileName);
        }
    }

    public class Product
    {
        [XmlAttribute("ProductID")]
        public int ID { get; set; }

        public string Name { get; set; }

        public string Description { get; set; }
    }

and for the XmlSerialize() and XmlDeserialize() which you see above, use these extension methods that I wrote a few years back:

public static class XmlExtensions
{
    /// <summary>
    /// Deserializes the XML data contained by the specified System.String
    /// </summary>
    /// <typeparam name="T">The type of System.Object to be deserialized</typeparam>
    /// <param name="s">The System.String containing XML data</param>
    /// <returns>The System.Object being deserialized.</returns>
    public static T XmlDeserialize<T>(this string s)
    {
        if (string.IsNullOrEmpty(s))
        {
            return default(T);
        }

        var locker = new object();
        var stringReader = new StringReader(s);
        var reader = new XmlTextReader(stringReader);
        try
        {
            var xmlSerializer = new XmlSerializer(typeof(T));
            lock (locker)
            {
                var item = (T)xmlSerializer.Deserialize(reader);
                reader.Close();
                return item;
            }
        }
        catch
        {
            return default(T);
        }
        finally
        {
            reader.Close();
        }
    }

    /// <summary>
    /// Deserializes the XML data contained in the specified file.
    /// </summary>
    /// <typeparam name="T">The type of System.Object to be deserialized.</typeparam>
    /// <param name="fileInfo">This System.IO.FileInfo instance.</param>
    /// <returns>The System.Object being deserialized.</returns>
    public static T XmlDeserialize<T>(this FileInfo fileInfo)
    {
        string xml = string.Empty;
        using (FileStream fs = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read))
        {
            using (StreamReader sr = new StreamReader(fs))
            {
                return sr.ReadToEnd().XmlDeserialize<T>();
            }
        }
    }

    /// <summary>
    /// <para>Serializes the specified System.Object and writes the XML document</para>
    /// <para>to the specified file.</para>
    /// </summary>
    /// <typeparam name="T">This item's type</typeparam>
    /// <param name="item">This item</param>
    /// <param name="fileName">The file to which you want to write.</param>
    /// <returns>true if successful, otherwise false.</returns>
    public static bool XmlSerialize<T>(this T item, string fileName)
    {
        return item.XmlSerialize(fileName, true);
    }

    /// <summary>
    /// <para>Serializes the specified System.Object and writes the XML document</para>
    /// <para>to the specified file.</para>
    /// </summary>
    /// <typeparam name="T">This item's type</typeparam>
    /// <param name="item">This item</param>
    /// <param name="fileName">The file to which you want to write.</param>
    /// <param name="removeNamespaces">
    ///     <para>Specify whether to remove xml namespaces.</para>para>
    ///     <para>If your object has any XmlInclude attributes, then set this to false</para>
    /// </param>
    /// <returns>true if successful, otherwise false.</returns>
    public static bool XmlSerialize<T>(this T item, string fileName, bool removeNamespaces)
    {
        object locker = new object();

        XmlSerializerNamespaces xmlns = new XmlSerializerNamespaces();
        xmlns.Add(string.Empty, string.Empty);

        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));

        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Indent = true;
        settings.OmitXmlDeclaration = true;

        lock (locker)
        {
            using (XmlWriter writer = XmlWriter.Create(fileName, settings))
            {
                if (removeNamespaces)
                {
                    xmlSerializer.Serialize(writer, item, xmlns);
                }
                else { xmlSerializer.Serialize(writer, item); }

                writer.Close();
            }
        }

        return true;
    }
}

I hope this is useful. If not, please give us more info on your situation as already requested.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM