0

我有以下课程

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

我想从对象创建一个 XML 文件。如果产品 id 存在,则更新节点,否则在 xml 文件中添加或附加节点。

我正在使用以下代码序列化对象

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

但它每次都从头开始创建文件,所以如果文件中存在数据,它会用新的文件覆盖它。

所以我正在寻找在xml中添加/附加节点的机制,根据ProductID获取节点并删除节点。

该类可以使用更多数据成员进行扩展,因此代码应该是动态的,因此我不必在代码中指定子元素,我只希望它在类级别。

希望有人可以提供帮助

我正在寻找的结构如下

<?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>
4

3 回答 3

0

应该让您朝着更好的方向开始;即使用 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"));

现在,您应该能够弄清楚如何反序列化它。您也可以将整个内容加载回内存并使用新产品进行更新,然后重新保存。如果您有太多产品而无法做到这一点,那么您需要一个数据库,而不是 XML。

于 2013-03-13T10:34:37.570 回答
0

在这里,如果您不确定如何反序列化,您可以这样做:

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; }
    }

对于你在上面看到的XmlSerialize()and XmlDeserialize(),使用我几年前写的这些扩展方法:

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;
    }
}

我希望这很有用。如果没有,请按照已要求向我们提供有关您的情况的更多信息。

于 2013-03-13T11:55:05.837 回答
0

我不明白这个问题:

  1. 将 xml 反序列化为 objext
  2. 对对象进行更改
  3. 序列化更新的对象
于 2013-03-13T10:15:32.033 回答