Update child nodes with data from datatable in XmlNode. - CSharp System.Xml

CSharp examples for System.Xml:XML Node

Description

Update child nodes with data from datatable in XmlNode.

Demo Code

// All rights reserved.
using System.Diagnostics;
using System.Collections.Specialized;
using System.Xml;
using System.Data;
using System;/*www. ja v  a2  s .  c  o m*/

public class Main{
        /// <summary>
        /// Update child nodes with data from datatable.
        /// Note that the datatable requires a primary key column defined.
        /// </summary>
        /// <param name="parentNode"></param>
        /// <param name="table"></param>
        public static void UpdateChildNodesWithDataTable(XmlNode parentNode, DataTable table)
        {
            DataColumn[] primaryKeyColumns = table.PrimaryKey;
            if (primaryKeyColumns == null)
                throw new Exception("Can not update Child nodes with Table because the table doesn't have a primary key column");
            else
            {
                UpdateChildNodesWithDataTable(parentNode, table, primaryKeyColumns[0].ColumnName);
            }
        }
        /// <summary>
        /// Updates the child nodes of "parentNode" by using the fields from a datatable.
        /// </summary>
        /// <param name="parentNode"></param>
        /// <param name="table"></param>
        /// <param name="keyField">The column name of the datatable that acts as a primary key.</param>
        /// <remarks>
        /// The child nodes that will be updated must have attribute fields that correspond to
        /// the DataTable.  The "keyField" will be used to identify the attribute that serves as 
        /// an identifier of the rows.  The datatable can have less fields than the nodes so
        /// you have the chance to update smaller subsets.
        /// Make sure that you did not call "AcceptChanges" before passing the datatable or this
        /// function will not find any change.
        /// </remarks>
        public static void UpdateChildNodesWithDataTable(XmlNode parentNode, DataTable table, string keyField)
        {
            if (parentNode == null)
            {
                throw new ArgumentNullException("Unable to update child nodes because parentNode is null");
            }
            if (parentNode.HasChildNodes)
            {
                XmlNode firstNode = parentNode.ChildNodes[0];
                //
                // Verify that the fields of first child node match the fields in the data table
                // note that it's ok if the datatable has fewer fields than the nodes.
                string missingFields = "";
                StringCollection columnNames = new StringCollection();
                foreach (DataColumn col in table.Columns)
                {
                    if (firstNode.Attributes[col.ColumnName] == null)
                    {
                        if (missingFields.Length == 0)
                            missingFields = col.ColumnName;
                        else
                            missingFields += ", " + col.ColumnName;
                    }
                    else
                        columnNames.Add(col.ColumnName);
                }

                if (missingFields.Length > 0)
                {
                    throw new Exception("Unable to update nodes with datatable because the nodes are missing the fields: " + missingFields);
                }

                ///
                /// Remove nodes that got deleted from datatable
                ///
                DataTable currTable = table.GetChanges(DataRowState.Deleted);
                if (currTable != null)
                {
                    //since there is no way to tell which rows got deleted then just remove all nodes 
                    //that are not present in the datatable.

                    XmlNode nodeToDelete;
                    Trace.WriteLine("Rows Deleted:");
                    foreach (DataRow row in table.Rows)
                    {
                        string keyValue = row[keyField].ToString();
                        nodeToDelete = SelectNode(parentNode, keyField, keyValue);
                        Trace.WriteLine(keyValue);
                        if (nodeToDelete != null)
                        {
                            parentNode.RemoveChild(nodeToDelete);
                        }
                    }
                }

                ///
                /// Update nodes with changes made on the datatable
                ///
                currTable = table.GetChanges(DataRowState.Modified);
                if (currTable != null)
                {
                    XmlNode nodeToUpdate;
                    Trace.WriteLine("Rows Changed:");
                    foreach (DataRow row in currTable.Rows)
                    {
                        string keyValue = row[keyField].ToString();
                        Trace.WriteLine(keyValue);
                        nodeToUpdate = SelectNode(parentNode, keyField, keyValue);
                        if (nodeToUpdate == null) throw new Exception("Unable to update node with '" + keyField + "=" + keyValue + "' because it doesn't exist");

                        string valueToSet;
                        foreach (string colName in columnNames)
                        {
                            if (colName == keyField) continue;
                            valueToSet = row[colName].ToString();
                            SetAttributeValue(nodeToUpdate, colName, valueToSet);
                        }
                    }
                }

                ///
                /// Add new nodes to match new rows added to datatable
                /// 
                currTable = table.GetChanges(DataRowState.Added);
                if (currTable != null)
                {
                    XmlNode newNode;
                    string keyValue;
                    XmlDocument doc = parentNode.OwnerDocument;
                    Trace.WriteLine("Rows Added:");
                    foreach (DataRow row in currTable.Rows)
                    {
                        keyValue = row[keyField].ToString();
                        Trace.WriteLine(keyValue);
                        if (SelectNode(parentNode, keyField, keyValue) == null)
                        {
                            newNode = doc.CreateElement(firstNode.Name);
                            CopyAttributes(row, newNode);
                            parentNode.AppendChild(newNode);
                        }
                        else
                        {
                            throw new Exception("Can not add duplicate nodes. Row with '" + keyField + "=" + keyValue + " was not added. Error Updating Nodes from Table");
                        }
                    }
                }
                table.AcceptChanges();
            }

        }
}

Related Tutorials