如何使用Repeater项有效地更新XML文件?

时间:2013-01-29 22:15:12

标签: c# xml web repeater

我正在将XML文件绑定到转发器,文本框中的每个项目。触发Save操作时,我需要将更改写回XML文件。我的问题是什么是最有效的方法,记住XML文件非常小。

我能想到三个,我不知道哪个最好:

  1. 循环转发器,在XML文件中找到匹配的ID,更新这些节点
  2. 循环XML文件,在转发器中查找匹配的ID,更新这些节点
  3. 编写新的XML文件(替换旧文件)
  4. 谢谢!

    更新了我的XML文件的示例:

    <?xml version="1.0" encoding="UTF-8"?>
    <Link>
    <LinkNode>
    <Section>New York</Section>
    <Header>New York</Header>
    <Item>IT/ Phone Support</Item>
    <Details>Ext 5.8115</Details>
    <ID>0</ID>
    <HyperLink>0</HyperLink>
    </LinkNode>
    <LinkNode>
    <Section>New York</Section>
    <Header />
    <Item>Email</Item>
    <Details>info@gld.com</Details>
    <ID>1</ID>
    <HyperLink>2</HyperLink>
    </LinkNode>
    </Link>
    

    这是我的班级:

    public class Link
    {
        public String Section { get; set; }
        public String Header { get; set; }
        public String Item { get; set; }
        public String Details { get; set; }
        public Int32 ID { get; set; }
        public Int32 Hyperlink { get; set; }
    }
    

    My Links构造函数:

     var LinksList = new List<Links>();
     var query = links_xml.Root.Descendants("LinkNode").Select(d => d);
    
                foreach (var q in query)
                {
    
    
    
                    var linklist = new Links((!string.IsNullOrEmpty(q.Element("Header").Value)) ? q.Element("Header").Value : "",
                        (!string.IsNullOrEmpty(q.Element("Item").Value)) ? q.Element("Item").Value : "",
                        (!string.IsNullOrEmpty(q.Element("Details").Value)) ? q.Element("Details").Value : "",
                        (int)q.Element("ID"), (int)q.Element("HyperLink"));
                    LinksList.Add(linklist);
    
                }
    

2 个答案:

答案 0 :(得分:1)

您还可以创建包含所需属性的类对象。将XML的读取和写入放在DAL层中。这样,您的DAL传递并接收List<Url>这些对象,并从应用程序的其余部分抽象数据访问(在您的情况下为XML)。

如果您选择更改数据存储方法(更改为SQL等),则只需更改DAL方法,其余代码不受影响。

如果您想要一些代码来说明,请告诉我。

编辑:(一些代码)

假设您的元素具有以下属性,那么这将是您的类:

public class Url
{
     public int Id {get; set;}
     public string DisplayName {get; set;}
     public string Url {get; set;}
}

然后你的DAL类看起来像这样:

/// <summary>
/// Handles data access for Url entities
/// </summary>
public static class UrlDAL
{
    /// <summary>
    /// The path where the file resides
    /// </summary>
    const string __FilePath = @"~\App_Data\";
    /// <summary>
    /// The name of the file
    /// </summary>
    const string __FileName = "UrlList.xml";
    /// <summary>
    /// The name of the temporary file. Used to keep a copy of the file if saving the new file fails.
    /// </summary>
    const string __FileNameTemp = "UrlList_TEMP.xml";

    /// <summary>
    /// Retrieves a list of url entity objects
    /// </summary>
    /// <returns></returns>
    internal static List<Url> Retrieve()
    {
        List<Url> urls = null;

        try
        {
            //read xml file
            XDocument data  = XDocument.Load(HttpContext.Current.Server.MapPath(Path.Combine(UrlDAL.__FilePath, UrlDAL..__FileName)));
            //convert to list
            urls = Xml.DeserializeCollection<Url>(data);
        }
        catch (Exception e)
        {
            //perform logging / error handling
        }

        return urls;

    }

    /// <summary>
    /// Saves the list of Url entities 
    /// </summary>
    /// <param name="urls">The list of url objects to save</param>
    internal static void Create(List<Url> urls)
    {

        try
        {
            //convert list into xml document
            XDocument file = Xml.SerializeCollection<Url>(urls);
            //rename the old file so you have a copy of it if saving the new file fails
            File.Copy(Path.Combine(UrlDAL.__FilePath, UrlDAL.__FileName), Path.Combine(UrlDAL.__FilePath, UrlDAL.__FileNameTemp));
            //saving the new file will overwrite the existing file
            file.Save(UrlDAL.__FilePath);
            //delete the old file
            File.Delete(Path.Combine(UrlDAL.__FilePath, UrlDAL.__FileNameTemp));
        }
        catch (Exception e)
        {
            //perform logging / error handling
            //you should also alert yourself of this error so you can manually restore the old file
        }

    }

}

这些是用于XML序列化/反序列化的扩展方法:

public static class Xml
{
    /// <summary>
    /// Converts an XDoc into a List<T> of entities
    /// </summary>
    /// <typeparam name="T">Any serializable object</typeparam>
    /// <param name="doc"></param>
    /// <returns></returns>
    public static List<T> DeserializeCollection<T>(XDocument doc)
    {
        if (doc == null)
            return null;

        try
        {
            XmlSerializer serializer = new XmlSerializer(typeof(List<T>));
            XmlReader reader = doc.CreateReader();
            List<T> result = (List<T>)serializer.Deserialize(reader);
            reader.Close();
            return result;
        }
        catch (Exception e)
        {
            //perform logging / error handling
            return null;
        }

    }

    /// <summary>
    /// Converts a List<T> of entities into an XDoc.
    /// </summary>
    /// <typeparam name="T">Any serializable object</typeparam>
    /// <param name="paramList"></param>
    public static XDocument SerializeCollection<T>(List<T> paramList)
    {
        if (paramList == null)
            return null;

        XDocument doc = new XDocument();

        try
        {
            XmlSerializer serializer = new XmlSerializer(paramList.GetType());
            XmlWriter writer = doc.CreateWriter();
            serializer.Serialize(writer, paramList);
            writer.Close();
            return doc;
        }
        catch (Exception e)
        {
            //perform logging / error handling
            return null;
        }

    }
}

不要忘记添加对以下命名空间的引用:

using System.IO;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;

所有这一切,你都会这样称呼DAL:

//to retrieve the list of urls
List<Url> urls = UrlDAL.Retrieve();
//to save the new list of urls to an xml file
List<Url> urls = [BUILD URL ENTITIES FROM REPEATER];
UrlDAL.Create(urls)

编辑:创建XML的提示

为了避免任何反序列化XML的问题(XML可能非常挑剔它将要解析的内容),我倾向于创建一些(或所有)我想在代码中使用的类并通过Xml.Serialize运行List方法。然后我使用在那里创建的xml作为创建XML文件的起点。

编辑从转发器创建实例

当您遍历转发器中的每个项目时,您可以像这样使用.NET的对象初始化程序

List<Links> links = new List<Links>();
foreach (RepeaterItem item in rptLinks.Items)
{
   //find all your controls and their values
   string details = ((TextBox)e.Item.Findcontrol("txtDetails")).Text;
   //do this for each control

   //use object initialization here
   links.Add(new Link {Details = details, [PROPERTY NAME] = [REPEATER ITEM VALUE], etc});
}

可以在MSDN上找到有关此功能的详细说明:Object and Collection Initializers (C# Programming Guide)

HTH

答案 1 :(得分:0)

使用XmlDocument加载xml,然后浏览它以查找 包含您要更改的值的元素。

System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
xmlDocument.Load(<filename or stream>);

Now, choose the most suitable method for you to find the elements or
attributes you want to change:

// For example:
XmlNodeList elemList = xmlDocument .GetElementsByTagName("Machine");
for (int i=0; i < elemList.Count; i++)
{
elemList[i].InnerXml = "Whateveryouwant";
}

然后,调用Save方法保存更改。

xmlDocument.Save(...);