PDA

View Full Version : Edit an Existing XML Node!


hodgesp
09-14-2007, 06:55 PM
Greetings Programs! (Remember Tron):D

It's me again. I got excellent help last time from PremiumBlend

I have another querstion. I have this xml project in c# .net. I am able to create the file add nodes, with attributes in standard form objectects and a data grid.

How do I replace/edit exsisting XML node values? I'm using form objects; textbox, datagrid, dropdownlist etc...

I was able to delete and insert new node and values but how can I change exisiting ones?

Example: How Can I take This:

- <Section2>
<text>Section 2 Direct Labor Rates and Hours</text>
<cost EQ="10" UM="Hours" Rate="120">engineer 1</cost>
<cost EQ="10" UM="Hours" Rate="135.98">engineer</cost>
<cost EQ="11" UM="Hours" Rate="345.98">Mechanic 1</cost>
</Section2>


And change the values to this?


- <Section2>
<text>Section 2 - New Text I added to Update this tag</text>
<cost EQ="40" UM="Hours" Rate="199.99">Programmer</cost>
<cost EQ="20" UM="Hours" Rate="165.23">Buyer</cost>
<cost EQ="11" UM="Hours" Rate="345.98">Mechanic 1</cost>
</Section2>


Just taking it step by step while I learn.....:cool:

SouthwaterDave
09-15-2007, 06:39 PM
There are many ways to do this but here is one. First load the XML into an XmlDocument object (I have assumed it is in a file called c:\stuff.xml):

XmlDocument doc = new XmlDocument();
doc.Load("c:\\stuff.xml");

Then find and update the first node (which is the first node named Section2 at any level in the XML, followed by its first child node named text):

XmlNode node = doc.SelectSingleNode("//Section2/text");
node.InnerText = "Section 2 - New Text I added to Update this tag";

Then the second:

node = node.NextSibling;
node.Attributes("EQ").Value = 40;
node.Attributes("Rate").Value = 199.99;
node.InnerText = "Progammer";

...etc.

PremiumBlend
09-16-2007, 09:55 PM
So I'm not exactly sure how you have everything set up, but as long as you have an ItemCommand for each databound item, you can do something like this.

private void DataGrid1_ItemCommand(object sender, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
if (e.CommandName == "Edit")
{
XmlDocument xmlFile = new XmlDocument();
xmlFile.Load(fileName);
String id = ((XmlElement)e.Item.DataItem).Attributes["id"].InnerText;
xmlFile.GetElementById(id).Attributes["cost"].InnerText = ((TableRow)e.Item).Cells[0].Text;
xmlFile.Save(fileName);
}
}


This code might not work exactly like your project requires, but I think you'll be able to get it working if you play around with it for a little bit.

This example would also require the use of a unique attribute (I used 'id') for every cost element. You'd have to add this to the xml file and figure out a way to create a rule for creating new unique IDs.

P.S. Don't forget to register your event handler:

this.DataGrid1.ItemCommand += new DataGridCommandEventHandler(DataGrid1_ItemCommand);

hodgesp
09-17-2007, 11:07 PM
Well I experimented with both your responses and some of my own and came up with this:


private void DataGrid1_UpdateCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.Load(fileName);
//---Value given for the <cost> element
TextBox tbCostDescrEdit = new TextBox();
tbCostDescrEdit = (TextBox)e.Item.FindControl("tbCostDescrEdit");//
XmlNode sNodeU = doc.SelectSingleNode("/Root/Section2/cost");
sNodeU.InnerText = tbCostDescrEdit.Text;
//---//
TextBox tbCostEQEdit = new TextBox();
tbCostEQEdit = (TextBox)e.Item.FindControl("tbCostEQEdit");//
sNodeU.Attributes["EQ"].InnerText = tbCostEQEdit.Text;
//---//
DropDownList ddlCostUMEdit = new DropDownList();
ddlCostUMEdit = (DropDownList)e.Item.FindControl("ddlCostUMEdit");//
sNodeU.Attributes["UM"].InnerText = ddlCostUMEdit.SelectedValue;
//---//
TextBox tbCostRateEdit = new TextBox();
tbCostRateEdit = (TextBox)e.Item.FindControl("tbCostRateEdit");
sNodeU.Attributes["Rate"].InnerText = tbCostRateEdit.Text;
//---//
doc.Save(fileName);
DataGrid1.EditItemIndex = -1;
DataGrid1.ShowFooter = true;
bindGrid();

}



Works for updating the Cost Tags and the DataGrid Both, EXCEPT! :confused: No matter what DataRow In the DataGrid I update/Edit, The changes are passed to the First <cost> tag in the Xml file and the first row in the DataGrid.:confused:

I'm attempting to use the e.Item.ItemIndex, Any Suggestions? :D

To Refresh this is my basic xml schema:

<UserName>George O Jungle</UserName>
<FileTitle>xml1</FileTitle>
<FileDate>09/17/2007</FileDate>
- <Section1>
<text>Section 1 General Instruction</text>
</Section1>
- <Section2>
<text>Section 2 Direct Labor Rates and Hours </text>
<cost EQ="10" UM="Hours" Rate="10">mechanic 1</cost>
<cost EQ="10" UM="Hours" Rate="14">Driver</cost>
<cost EQ="40" UM="Hours" Rate="124.47">programmer 1</cost>
</Section2>

PremiumBlend
09-18-2007, 02:07 AM
Can you post your code for the whole page and the whole xml file please?

hodgesp
09-18-2007, 02:59 PM
My c#


using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Web.Caching;
using System.Xml;
using System.Xml.XPath;

using System.Text.RegularExpressions;

namespace CostEstimating
{
/// <summary>
/// Summary description for ce2.
/// </summary>
public class ce2 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Label Label1;
protected System.Web.UI.WebControls.Label Label5;
protected System.Web.UI.WebControls.HyperLink fileLink;
protected System.Web.UI.WebControls.Label Label2;
protected System.Web.UI.WebControls.TextBox TextBox1;
protected System.Web.UI.WebControls.DataGrid DataGrid1;
protected System.Web.UI.WebControls.Button go2ce3;
protected System.Web.UI.WebControls.Button btnAddCost;
protected System.Web.UI.WebControls.Panel Panel2;
protected System.Web.UI.WebControls.Panel Panel1;
protected System.Web.UI.WebControls.Label lblSec2Total;
public string fileName;
public string strDescr;
public string strEQ;
public string strUM;
public string strRate;
public int intDot;
public string xTotal;
public decimal dblVal;
protected System.Web.UI.WebControls.Label Label4;
protected System.Web.UI.WebControls.Label Label3;
protected System.Web.UI.WebControls.TextBox tbMode;


private void Page_Load(object sender, System.EventArgs e)
{
ViewState["sec2Total"] = 0;
// Session["fileName"] = "xml1"; //---debugging script---//
fileName = "c:\\" + Session["fileName"].ToString()+ ".xml";
this.fileLink.Text = Session["fileName"].ToString();
this.fileLink.NavigateUrl = fileName.ToString();
//---//
if(!Page.IsPostBack)
{
this.tbMode.Text = Request.QueryString["mode"];

if(this.tbMode.Text != "create")
{
this.tbMode.Text = "edit";
XmlDocument xmlFile = new XmlDocument();
xmlFile.Load(fileName);
//Create an XPathNavigator
XPathNavigator xpNav = xmlFile.CreateNavigator();
XPathNodeIterator iter = xpNav.Select("//Section2/text");
iter.MoveNext();
this.TextBox1.Text = iter.Current.Value;
}
else
{
this.tbMode.Text = "create";
}
}
}


private void bindGrid()
{
XmlDocument xmlFile = new XmlDocument();
xmlFile.Load(fileName);
DataGrid1.DataSource = xmlFile.GetElementsByTagName("cost");
DataGrid1.DataBind();
}


#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnAddCost.Click += new System.EventHandler(this.btnAddCost_Click);
this.DataGrid1.ItemCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.DataGrid1_ItemCommand);
this.DataGrid1.CancelCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.DataGrid1_CancelCommand);
this.DataGrid1.EditCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.DataGrid1_EditCommand);
this.DataGrid1.UpdateCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.DataGrid1_UpdateCommand);
this.DataGrid1.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.DataGrid1_ItemDataBound);
this.go2ce3.Click += new System.EventHandler(this.go2ce3_Click);
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion


private void go2ce3_Click(object sender, System.EventArgs e)
{
XmlTextReader reader = new XmlTextReader(fileName);
XmlDocument doc = new XmlDocument();
doc.Load(reader);
reader.Close();
doc.Save(fileName);
Session["TheCount"] = 0;
Response.Redirect("ce3.aspx?mode=" + "create" );
}


private void btnAddCost_Click(object sender, System.EventArgs e)
{
string strLen = this.TextBox1.Text;
if(strLen.Length > 0)
{
XmlDocument doc = new XmlDocument();
doc.Load(fileName);

XmlElement root = doc.DocumentElement;
if(this.tbMode.Text == "create")
{
XmlElement s1 = doc.CreateElement("Section2");
s1.InnerXml = "<text>" + this.TextBox1.Text + "</text>".Trim() ;
root.AppendChild(s1);
this.tbMode.Text = "addCost";
btnAddCost.Text ="Update Section 2 Comment";

}
else
{
XmlNode xNode = doc.SelectSingleNode("/Root/Section2/text");
xNode.InnerText = this.TextBox1.Text;
}
doc.Save(fileName);
bindGrid();
// btnAddCost.Visible=false; //--turn this off so you won't create a duplicate tag.
}
else
{
RegisterStartupScript("TheAlert", "<script language=\"JavaScript\">" + "\n alert('You Must Enter Section 2 Direct Labor Rates and Hours Description Prior To Proceeding...');" + "\n </script>");
}
}


private void DataGrid1_CancelCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
DataGrid1.EditItemIndex = -1;
bindGrid();
}


private void DataGrid1_ItemCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.Load(fileName);
XmlNode s2 = doc.SelectSingleNode("/Root/Section2");
XmlElement cost = null;
if(e.CommandName == "Insert")
{
//---Create New cost XML Element <cost></cost>---//
cost = doc.CreateElement("cost");
//---New Attribute(s)
XmlAttribute attribEQ = doc.CreateAttribute("EQ");
XmlAttribute attribUM = doc.CreateAttribute("UM");
XmlAttribute attribRate = doc.CreateAttribute("Rate");
//--Value given for the new attribute(s)
//--EQ Attribute---//
TextBox tbCostEQAdd = new TextBox();
tbCostEQAdd = (TextBox)e.Item.FindControl("tbCostEQAdd");
attribEQ.Value = tbCostEQAdd.Text;
//--UM Attribute---//
DropDownList ddlCostUMAdd = new DropDownList();
ddlCostUMAdd = (DropDownList)e.Item.FindControl("ddlCostUMAdd");
attribUM.Value = ddlCostUMAdd.SelectedValue;
//--Rate Attribute---//
TextBox tbCostRateAdd = new TextBox();
tbCostRateAdd = (TextBox)e.Item.FindControl("tbCostRateAdd");
attribRate.Value = tbCostRateAdd.Text;
//---Attach the attribute to the XML element
cost.SetAttribute(attribEQ.Name,tbCostEQAdd.Text);
cost.SetAttribute(attribUM.Name,ddlCostUMAdd.SelectedValue);
cost.SetAttribute(attribRate.Name,tbCostRateAdd.Text);
//---Value given for the <cost> element
TextBox tbCostDescrAdd = new TextBox();
tbCostDescrAdd = (TextBox)e.Item.FindControl("tbCostDescrAdd");
cost.InnerText = tbCostDescrAdd.Text;
try
{
Decimal.Parse(tbCostEQAdd.Text);
Decimal.Parse(tbCostRateAdd.Text);
string strLenU = ddlCostUMAdd.SelectedValue;
string strLenD = tbCostDescrAdd.Text;

if(strLenU.Length > 0 && strLenD.Length > 0)
{
s2.AppendChild(cost);
doc.Save(fileName);
bindGrid();
}
else
{
RegisterStartupScript("TheAlert", "<script language=\"JavaScript\">" + "\n alert('You Must Enter A Cost UM And A Description');" + "\n </script>");
}
}
catch
{
RegisterStartupScript("TheAlert", "<script language=\"JavaScript\">" + "\n alert('Input Values For Est Qty, Rate Must Be Numeric/Decimal ##.##');" + "\n </script>");
}
}

}

private void DataGrid1_ItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
{
switch(e.Item.ItemType)
{
case ListItemType.AlternatingItem: //---AlternatingItem---//
//---Description InnerText---//
strDescr = ((XmlElement)e.Item.DataItem).InnerText;
if(strDescr.Length > 0)
{
((TableRow)e.Item).Cells[1].Text = strDescr.ToString().Trim();
}
//---EQ attribute---//
strEQ = ((XmlElement)e.Item.DataItem).Attributes["EQ"].InnerText;
intDot = strEQ.IndexOf(".");
if(intDot != -1)
{
((TableRow)e.Item).Cells[2].Text = String.Format("{0:d}", strEQ.ToString());
}
else
{
((TableRow)e.Item).Cells[2].Text = String.Format("{0:d}", strEQ.ToString() + ".00");
}
//---UM attribute---//
strUM = ((XmlElement)e.Item.DataItem).Attributes["UM"].InnerText;
if(strUM.Length > 0)
{
((TableRow)e.Item).Cells[3].Text = strUM.ToString().Trim();
}
//---Rate attribute---//
strRate = ((XmlElement)e.Item.DataItem).Attributes["Rate"].InnerText;
intDot = strRate.IndexOf(".");
if(intDot != -1)
{
((TableRow)e.Item).Cells[4].Text = String.Format("$ {0:c}", strRate.ToString());
}
else
{
((TableRow)e.Item).Cells[4].Text = String.Format("$ {0:c}", strRate.ToString() + ".00");
}
xTotal = Decimal.Multiply( Decimal.Parse( strRate.ToString() ), Decimal.Parse(strEQ.ToString())).ToString() ;
dblVal = Math.Round( Decimal.Parse(xTotal.ToString()),2 );
((TableRow)e.Item).Cells[5].Text = String.Format("$ {0:c}",dblVal.ToString());
//--total rollup--//
ViewState["sec2Total"] = Decimal.Add(Decimal.Parse( ViewState["sec2Total"].ToString() ), Decimal.Parse(xTotal.ToString())).ToString();
dblVal = Math.Round( Decimal.Parse(ViewState["sec2Total"].ToString()),2 );
this.lblSec2Total.Text = String.Format("$ {0:c}",ViewState["sec2Total"].ToString());
break;
case ListItemType.Item: //---Item---//
//---Description InnerText---//
strDescr = ((XmlElement)e.Item.DataItem).InnerText;
if(strDescr.Length > 0)
{
((TableRow)e.Item).Cells[1].Text = strDescr.ToString().Trim();
}
//---EQ attribute---//
strEQ = ((XmlElement)e.Item.DataItem).Attributes["EQ"].InnerText;
intDot = strEQ.IndexOf(".");
if(intDot != -1)
{
((TableRow)e.Item).Cells[2].Text = String.Format("{0:d}", strEQ.ToString());
}
else
{
((TableRow)e.Item).Cells[2].Text = String.Format("{0:d}", strEQ.ToString() + ".00");
}
//---UM attribute---//
strUM = ((XmlElement)e.Item.DataItem).Attributes["UM"].InnerText;
if(strUM.Length > 0)
{
((TableRow)e.Item).Cells[3].Text = strUM.ToString().Trim();
}
//---Rate attribute---//
strRate = ((XmlElement)e.Item.DataItem).Attributes["Rate"].InnerText;
intDot = strRate.IndexOf(".");
if(intDot != -1)
{
((TableRow)e.Item).Cells[4].Text = String.Format("$ {0:c}", strRate.ToString());
}
else
{
((TableRow)e.Item).Cells[4].Text = String.Format("$ {0:c}", strRate.ToString() + ".00");
}
//--Est Total Colum---//
xTotal = Decimal.Multiply( Decimal.Parse( strRate.ToString() ), Decimal.Parse(strEQ.ToString())).ToString() ;
dblVal = Math.Round( Decimal.Parse(xTotal.ToString()),2 );
((TableRow)e.Item).Cells[5].Text = String.Format("$ {0:c}",dblVal.ToString());
//--total rollup--//
ViewState["sec2Total"] = Decimal.Add(Decimal.Parse( ViewState["sec2Total"].ToString() ), Decimal.Parse(xTotal.ToString())).ToString();
dblVal = Math.Round( Decimal.Parse(ViewState["sec2Total"].ToString()),2 );
this.lblSec2Total.Text = String.Format("$ {0:c}",ViewState["sec2Total"].ToString());
break;
default:
break;
}

}

private void DataGrid1_EditCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
this.DataGrid1.ShowFooter = false;
this.DataGrid1.EditItemIndex = e.Item.ItemIndex;
bindGrid();
}

private void DataGrid1_UpdateCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
if(e.Item.ItemIndex == this.DataGrid1.EditItemIndex)
{
XmlDocument doc = new XmlDocument();
doc.Load(fileName);
//---Value given for the <cost> element
TextBox tbCostDescrEdit = new TextBox();
tbCostDescrEdit = (TextBox)e.Item.FindControl("tbCostDescrEdit");//
XmlNode sNodeU = doc.SelectSingleNode("/Root/Section2/cost");
sNodeU.InnerText = tbCostDescrEdit.Text;
//---//
TextBox tbCostEQEdit = new TextBox();
tbCostEQEdit = (TextBox)e.Item.FindControl("tbCostEQEdit");//
sNodeU.Attributes["EQ"].InnerText = tbCostEQEdit.Text;
//---//
DropDownList ddlCostUMEdit = new DropDownList();
ddlCostUMEdit = (DropDownList)e.Item.FindControl("ddlCostUMEdit");//
sNodeU.Attributes["UM"].InnerText = ddlCostUMEdit.SelectedValue;
//---//
TextBox tbCostRateEdit = new TextBox();
tbCostRateEdit = (TextBox)e.Item.FindControl("tbCostRateEdit");
sNodeU.Attributes["Rate"].InnerText = tbCostRateEdit.Text;
//---//
doc.Save(fileName);
DataGrid1.EditItemIndex = -1;
DataGrid1.ShowFooter = true;
bindGrid();
}

}



}
}




my XML file, note each section after section 2 will be similar:


<?xml version="1.0" ?>
- <Root>
<UserName>George O Jungle</UserName>
<FileTitle>Xml1</FileTitle>
<FileDate>09/18/2007</FileDate>
- <Section1>
<text>Section 1: General Instructions: Place all General Instruction Comments in this section Here.</text>
</Section1>
- <Section2>
<text>Section 2 Direct Labor Rates and Hours. This is the first Section that will contain Itemized Cost Records. All folowing Sections will contain similar structures.</text>
<cost EQ="40" UM="Hours" Rate="123.17">Engineer I</cost>
<cost EQ="40" UM="Hours" Rate="115.18">Engineer II</cost>
<cost EQ="60" UM="Hours" Rate="172.13">Programmer I</cost>
<cost EQ="80" UM="Hours" Rate="97.27">Technical Writer</cost>
</Section2>
- <Section3>
<text>This is Section 3. I have yet to add the code to this page for Cost Records</text>
</Section3>
- <Section4>
<text>This is Section 4. I have yet to add the code to this page for Cost Records</text>
</Section4>
- <Section5>
<text>This is Section 5. I have yet to add the code to this page for Cost Records</text>
</Section5>
- <Section6>
<text>This is Section 6. The Summary Section.</text>
</Section6>
</Root>



I got most of my functionality, I just need to figure out how to edit the datagrid records correctly. Right now, no matter which record I try to edit I only update the first record in the grid which corresponds to the first <cost> tag in the Xml1 file under <section2>.

Also I get an error when attempting to delete a row now. "Object reference not set to an instance of an object."
I thought I had the code down, but guess not.

:confused: :confused: :confused:

PremiumBlend
09-20-2007, 04:06 PM
I highlighted the part of the code you need to replace and then what to replace it with is in the next Code block.


private void DataGrid1_UpdateCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
if(e.Item.ItemIndex == this.DataGrid1.EditItemIndex)
{
XmlDocument doc = new XmlDocument();
doc.Load(fileName);
//---Value given for the <cost> element
TextBox tbCostDescrEdit = new TextBox();
tbCostDescrEdit = (TextBox)e.Item.FindControl("tbCostDescrEdit");//
XmlNode sNodeU = doc.SelectSingleNode("/Root/Section2/cost");
sNodeU.InnerText = tbCostDescrEdit.Text;
//---//
TextBox tbCostEQEdit = new TextBox();
tbCostEQEdit = (TextBox)e.Item.FindControl("tbCostEQEdit");//
sNodeU.Attributes["EQ"].InnerText = tbCostEQEdit.Text;
//---//
DropDownList ddlCostUMEdit = new DropDownList();
ddlCostUMEdit = (DropDownList)e.Item.FindControl("ddlCostUMEdit");//
sNodeU.Attributes["UM"].InnerText = ddlCostUMEdit.SelectedValue;
//---//
TextBox tbCostRateEdit = new TextBox();
tbCostRateEdit = (TextBox)e.Item.FindControl("tbCostRateEdit");
sNodeU.Attributes["Rate"].InnerText = tbCostRateEdit.Text;
//---//
doc.Save(fileName);
DataGrid1.EditItemIndex = -1;
DataGrid1.ShowFooter = true;
bindGrid();
}

}



The code I highlighted in red is selecting one node from the Xml. This assumes that the XPath String you pass in will only return one result. Since you're asking for all 'code' elements in Section2, you'll get more than one, but since it is 'SelectSingleNode()', it returns only the first one in the list.


XmlNode sNodeU = null; //doc.SelectSingleNode("/Root/Section2/cost");
int iCostNode = 0;
XmlNodeList sNodeListU = doc.SelectNodes("/Root/Section2/cost");
foreach(XmlNode xNodeU in sNodeListU)
{
if(iCostNode == e.Item.ItemIndex) //If the index of the XmlNode == index of DataGrid Item...
{
sNodeU = xNodeU;
break;
}
iCostNode++;
}


What this code does is loops through the NodeList returned by 'SelectNodes()' until it encounters the index of the same 'Cost' node.

The 'SelectSingleNode()' function is probably the better way to go, but you would have to use unique ID attributes in the Xml. That is a good thing to have in your Xml document, but since you're able to add new ones, there probably isn't a good way to insert a unique ID. Hope this fixes it for you!

hodgesp
09-24-2007, 03:28 PM
Well I tried your approch and I got rid of the error but I didn't update anything directly. I went ahead and added and id attribute to the cost tag like so:


<?xml version="1.0"?>
<Root>
<UserName>George Jungle</UserName>
<FileTitle>Xml1</FileTitle>
<FileDate>09/24/2007</FileDate>
<Section1>
<text>WTS Cost Estimating Wizard Section 1: General Instructions</text>
</Section1>
<Section2>
<text>WTS Cost Estimating Wizard Section 2 Direct Labor Rates and Hours - I added this as an Edit</text>
<cost EQ="40" UM="Hours" Rate="235.19" id="sc2-0">Engineer I</cost>
<cost EQ="40" UM="Hours" Rate="290.87" id="sc2-1">Engineer II</cost>
<cost EQ="40" UM="Hours" Rate="160.20" id="sc2-2">Draftsman I</cost>
<cost EQ="20" UM="Hours" Rate="138.39" id="sc2-3">Technicla Writer</cost>
<cost EQ="20" UM="Hours" Rate="120.76" id="sc2-4">Tester I</cost>
<cost EQ="20" UM="Hours" Rate="120.76" id="sc2-5">Tester II</cost>
</Section2>
</Root>




However I took the basic idea and came up with this in the DataGrid1_UpdateCommand event:


if(e.Item.ItemIndex == this.DataGrid1.EditItemIndex)
{
XmlDocument doc = new XmlDocument();
doc.Load(fileName);
xpathQuery = ViewState["xpathQuery"].ToString();
//---Value given for the <cost> element
TextBox tbCostDescrEdit = new TextBox();
tbCostDescrEdit = (TextBox)e.Item.FindControl("tbCostDescrEdit");
//XmlNode sNodeU = doc.SelectSingleNode("/Root/Section2/cost[@id='sc2-2']");
XmlNode sNodeU = doc.SelectSingleNode(xpathQuery);
sNodeU.InnerText = tbCostDescrEdit.Text;
//---//
TextBox tbCostEQEdit = new TextBox();
tbCostEQEdit = (TextBox)e.Item.FindControl("tbCostEQEdit");//
sNodeU.Attributes["EQ"].InnerText = tbCostEQEdit.Text;
//---//
DropDownList ddlCostUMEdit = new DropDownList();
ddlCostUMEdit = (DropDownList)e.Item.FindControl("ddlCostUMEdit");//
sNodeU.Attributes["UM"].InnerText = ddlCostUMEdit.SelectedValue;
//---//
TextBox tbCostRateEdit = new TextBox();
tbCostRateEdit = (TextBox)e.Item.FindControl("tbCostRateEdit");
sNodeU.Attributes["Rate"].InnerText = tbCostRateEdit.Text;
//---//
doc.Save(fileName);
DataGrid1.EditItemIndex = -1;
DataGrid1.ShowFooter = true;
bindGrid();



Problem! For some reason, I can only successfully edit the Datagrid (the cost tags) when I hard code the id like so:
XmlNode sNodeU = doc.SelectSingleNode("/Root/Section2/cost[@id='sc2-2']");
And the variable that I'm using to hold my XPath Query throws an error:
:confused:
XmlNode sNodeU = doc.SelectSingleNode(xpathQuery);


Hmmm, Need to figure out why the variable throws the error. Also is this correct Xpath Sytax?
"/Section2/cost/InnerXml="Engeer I" and [@EQ='40'] and [@Rate='290.87']"

So Close Yet So Frustrating.........:mad:

PremiumBlend
09-24-2007, 07:27 PM
I see you're setting the value of xpathQuery from ViewState. Can you post the code where you are setting the ViewState variable? Also, are you sure that your value for xpathQuery is set and not equal to null?

XmlNode sNodeU = doc.SelectSingleNode(xpathQuery);


Also, the syntax for using "and" in XPath should be something like this:


"/Section2/cost[@EQ='40'][@Rate='290.87']"


You don't use 'and' or some other operator, just put them together. If you wanted any that include any elements that match those, you would want to use an "or" which is the | (pipe symbol).

I made a little tutorial a while back for xpath found here (live-xpath-xml-queries) (http://www.dumpsterdoggy.com/tutorials/?live-xpath-xml-queries), you could play around with that to get used to the syntax.

hodgesp
09-26-2007, 03:08 PM
Well I played with the update a bit untill I got it to work on the selected index row. I even got my delete event to work as well. I had a problem reindexing the id attribute so I wouldn't come up with duplicates after the delete, But I fixed that too. Check it out heres the code::thumbsup:


using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Web.Caching;
using System.Xml;
using System.Xml.XPath;

namespace CostEstimating
{
/// <summary>
/// Summary description for ce2.
/// </summary>
public class ce2 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Label Label1;
protected System.Web.UI.WebControls.Label Label5;
protected System.Web.UI.WebControls.HyperLink fileLink;
protected System.Web.UI.WebControls.Label Label2;
protected System.Web.UI.WebControls.TextBox TextBox1;
protected System.Web.UI.WebControls.DataGrid DataGrid1;
protected System.Web.UI.WebControls.Button go2ce3;
protected System.Web.UI.WebControls.Button btnAddCost;
protected System.Web.UI.WebControls.Panel Panel2;
protected System.Web.UI.WebControls.Panel Panel1;
protected System.Web.UI.WebControls.Label lblSec2Total;
protected System.Web.UI.WebControls.Label Label4;
protected System.Web.UI.WebControls.Label Label3;
protected System.Web.UI.WebControls.TextBox TextBox2;
protected System.Web.UI.WebControls.TextBox tbMode;
//---//
public string xpathQuery;
public string fileName;
public string strDescr;
public string strEQ;
public string strUM;
public string strRate;
public string strId;
public int intDot;
public string xTotal;
public decimal dblVal;
//---//


private void Page_Load(object sender, System.EventArgs e)
{
fileName = "c:\\" + Session["fileName"].ToString()+ ".xml";
ViewState["sec2Total"] = 0;
this.fileLink.Text = Session["fileName"].ToString();
this.fileLink.NavigateUrl = fileName.ToString();
//---//
if(!Page.IsPostBack)
{
this.tbMode.Text = Request.QueryString["mode"];

if(this.tbMode.Text != "create")
{
this.tbMode.Text = "edit";
XmlDocument xmlFile = new XmlDocument();
xmlFile.Load(fileName);
//Create an XPathNavigator
XPathNavigator xpNav = xmlFile.CreateNavigator();
XPathNodeIterator iter = xpNav.Select("//Section2/text");
iter.MoveNext();
this.TextBox1.Text = iter.Current.Value;
}
else
{
this.tbMode.Text = "create";
}
}
}


private void bindGrid()
{
XmlDocument xmlFile = new XmlDocument();
xmlFile.Load(fileName);
// DataGrid1.DataSource = xmlFile.GetElementsByTagName("//Section2/cost");
XmlNodeList sNodeListBG = xmlFile.SelectNodes("/Root/Section2/cost");
DataGrid1.DataSource = sNodeListBG;
DataGrid1.DataBind();
}


#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnAddCost.Click += new System.EventHandler(this.btnAddCost_Click);
this.DataGrid1.ItemCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.DataGrid1_ItemCommand);
this.DataGrid1.CancelCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.DataGrid1_CancelCommand);
this.DataGrid1.EditCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.DataGrid1_EditCommand);
this.DataGrid1.UpdateCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.DataGrid1_UpdateCommand);
this.DataGrid1.DeleteCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.DataGrid1_DeleteCommand);
this.DataGrid1.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.DataGrid1_ItemDataBound);
this.go2ce3.Click += new System.EventHandler(this.go2ce3_Click);
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion


private void go2ce3_Click(object sender, System.EventArgs e)
{
Response.Redirect("ce3.aspx?mode=" + "create" );
}


private void btnAddCost_Click(object sender, System.EventArgs e)
{
string strLen = this.TextBox1.Text;
if(strLen.Length > 0)
{
XmlDocument doc = new XmlDocument();
doc.Load(fileName);

XmlElement root = doc.DocumentElement;
if(this.tbMode.Text == "create")
{
XmlElement s2Text = doc.CreateElement("Section2");
s2Text.InnerXml = "<text>" + this.TextBox1.Text + "</text>".Trim() ;
root.AppendChild(s2Text);
this.tbMode.Text = "addCost";
btnAddCost.Text ="Update Section 2 Comment";
ViewState["intId"] = 0;//--used for cost id attribute value--//
}
else
{
//--edit the innerxml value of the parent node for this section---//
XmlNode xNode = doc.SelectSingleNode("/Root/Section2/text");
xNode.InnerText = this.TextBox1.Text;
}
doc.Save(fileName);
bindGrid();
// btnAddCost.Visible=false; //--turn this off so you won't create a duplicate tag.
}
else
{
RegisterStartupScript("TheAlert", "<script language=\"JavaScript\">" + "\n alert('You Must Enter Section 2 Direct Labor Rates and Hours Description Prior To Proceeding...');" + "\n </script>");
}
}


private void DataGrid1_CancelCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
DataGrid1.EditItemIndex = -1;
DataGrid1.ShowFooter = true;
bindGrid();
}


private void DataGrid1_DeleteCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.Load(fileName);
//---//
Label lblCostid= new Label();
lblCostid.Text = ((TableRow)e.Item).Cells[7].Text;
//---//
ViewState["xpathQuery"] = "\"/Section2/cost[@id='" + lblCostid.Text + "']\"";
xpathQuery = ViewState["xpathQuery"].ToString();
//---reindex the id attribute for the cost tags---//
XmlNode sNodeR = null;
int iCostNode = 0;
int iCostNode1 = 0;//--second counter for id numeric value update---//
XmlNodeList sNodeListR = doc.SelectNodes("/Root/Section2/cost");
foreach(XmlNode xNodeR in sNodeListR)
{
if(iCostNode == e.Item.ItemIndex)
{
sNodeR = xNodeR;
sNodeR.ParentNode.RemoveChild(sNodeR);
this .TextBox2.Text = e.Item.ItemIndex.ToString();
}
else
{
sNodeR = xNodeR;
sNodeR.Attributes["id"].InnerText = "sc2-" + iCostNode1;
iCostNode1++;
}
iCostNode++;
}
//---//
doc.Save(fileName);
//---//
bindGrid();

}


private void DataGrid1_ItemCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
if(e.CommandName == "Insert")
{
XmlDocument doc = new XmlDocument();
doc.Load(fileName);
XmlNode s2 = doc.SelectSingleNode("/Root/Section2");
XmlElement cost = null;
//---Create New cost XML Element <cost></cost>---//
cost = doc.CreateElement("cost");
//---New Attribute(s)
XmlAttribute attribEQ = doc.CreateAttribute("EQ");
XmlAttribute attribUM = doc.CreateAttribute("UM");
XmlAttribute attribRate = doc.CreateAttribute("Rate");
XmlAttribute attribId = doc.CreateAttribute("id");
//--Value given for the new attribute(s)
//--EQ Attribute---//
TextBox tbCostEQAdd = new TextBox();
tbCostEQAdd = (TextBox)e.Item.FindControl("tbCostEQAdd");
attribEQ.Value = tbCostEQAdd.Text;
//--UM Attribute---//
DropDownList ddlCostUMAdd = new DropDownList();
ddlCostUMAdd = (DropDownList)e.Item.FindControl("ddlCostUMAdd");
attribUM.Value = ddlCostUMAdd.SelectedValue;
//--Rate Attribute---//
TextBox tbCostRateAdd = new TextBox();
tbCostRateAdd = (TextBox)e.Item.FindControl("tbCostRateAdd");
attribRate.Value = tbCostRateAdd.Text;
//---ORIGINAL ID ATTRIBUTE VALUE---//
ViewState["intId"] = DataGrid1.Items.Count;
attribId.Value = "sc2-" + ViewState["intId"].ToString(); //--unique number id---//
//---Attach the attributes to the XML element---//
cost.SetAttribute(attribEQ.Name,tbCostEQAdd.Text);
cost.SetAttribute(attribUM.Name,ddlCostUMAdd.SelectedValue);
cost.SetAttribute(attribRate.Name,tbCostRateAdd.Text);
cost.SetAttribute(attribId.Name,attribId.Value); //--attach unique number id---//
//---InnerText value given for the <cost> element---//
TextBox tbCostDescrAdd = new TextBox();
tbCostDescrAdd = (TextBox)e.Item.FindControl("tbCostDescrAdd");
cost.InnerText = tbCostDescrAdd.Text;
try
{
Decimal.Parse(tbCostEQAdd.Text);
Decimal.Parse(tbCostRateAdd.Text);
string strLenU = ddlCostUMAdd.SelectedValue;
string strLenD = tbCostDescrAdd.Text;
if(strLenU.Length > 0 && strLenD.Length > 0)
{
s2.AppendChild(cost);
doc.Save(fileName);
bindGrid();
}
else
{
RegisterStartupScript("TheAlert", "<script language=\"JavaScript\">" + "\n alert('You Must Enter A Cost UM And A Description');" + "\n </script>");
}
}
catch
{
RegisterStartupScript("TheAlert", "<script language=\"JavaScript\">" + "\n alert('Input Values For Est Qty, Rate Must Be Numeric/Decimal ##.##');" + "\n </script>");
}
}
}


private void DataGrid1_ItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
{
switch(e.Item.ItemType)
{
case ListItemType.AlternatingItem: //---AlternatingItem---//
//---Description InnerText---//
strDescr = ((XmlElement)e.Item.DataItem).InnerText;
if(strDescr.Length > 0)
{
((TableRow)e.Item).Cells[1].Text = strDescr.ToString().Trim();
}
//---EQ attribute---//
strEQ = ((XmlElement)e.Item.DataItem).Attributes["EQ"].InnerText;
intDot = strEQ.IndexOf(".");
if(intDot != -1)
{
((TableRow)e.Item).Cells[2].Text = String.Format("{0:d}", strEQ.ToString());
}
else
{
((TableRow)e.Item).Cells[2].Text = String.Format("{0:d}", strEQ.ToString() + ".00");
}
//---UM attribute---//
strUM = ((XmlElement)e.Item.DataItem).Attributes["UM"].InnerText;
if(strUM.Length > 0)
{
((TableRow)e.Item).Cells[3].Text = strUM.ToString().Trim();
}
//---Rate attribute---//
strRate = ((XmlElement)e.Item.DataItem).Attributes["Rate"].InnerText;
intDot = strRate.IndexOf(".");
if(intDot != -1)
{
((TableRow)e.Item).Cells[4].Text = String.Format("$ {0:c}", strRate.ToString());
}
else
{
((TableRow)e.Item).Cells[4].Text = String.Format("$ {0:c}", strRate.ToString() + ".00");
}
//--row total--//
xTotal = Decimal.Multiply( Decimal.Parse( strRate.ToString() ), Decimal.Parse(strEQ.ToString())).ToString() ;
dblVal = Math.Round( Decimal.Parse(xTotal.ToString()),2 );
((TableRow)e.Item).Cells[5].Text = String.Format("$ {0:c}",dblVal.ToString());
//--id column--//
strId = ((XmlElement)e.Item.DataItem).Attributes["id"].InnerText;
((TableRow)e.Item).Cells[7].Text = String.Format("{0:n}", strId.ToString());
//--total rollup--//
ViewState["sec2Total"] = Decimal.Add(Decimal.Parse( ViewState["sec2Total"].ToString() ), Decimal.Parse(xTotal.ToString())).ToString();
dblVal = Math.Round( Decimal.Parse(ViewState["sec2Total"].ToString()),2 );
this.lblSec2Total.Text = String.Format("$ {0:c}",ViewState["sec2Total"].ToString());
break;
case ListItemType.Item: //---Item---//
//---Description InnerText---//
strDescr = ((XmlElement)e.Item.DataItem).InnerText;
if(strDescr.Length > 0)
{
((TableRow)e.Item).Cells[1].Text = strDescr.ToString().Trim();
}
//---EQ attribute---//
strEQ = ((XmlElement)e.Item.DataItem).Attributes["EQ"].InnerText;
intDot = strEQ.IndexOf(".");
if(intDot != -1)
{
((TableRow)e.Item).Cells[2].Text = String.Format("{0:d}", strEQ.ToString());
}
else
{
((TableRow)e.Item).Cells[2].Text = String.Format("{0:d}", strEQ.ToString() + ".00");
}
//---UM attribute---//
strUM = ((XmlElement)e.Item.DataItem).Attributes["UM"].InnerText;
if(strUM.Length > 0)
{
((TableRow)e.Item).Cells[3].Text = strUM.ToString().Trim();
}
//---Rate attribute---//
strRate = ((XmlElement)e.Item.DataItem).Attributes["Rate"].InnerText;
intDot = strRate.IndexOf(".");
if(intDot != -1)
{
((TableRow)e.Item).Cells[4].Text = String.Format("$ {0:c}", strRate.ToString());
}
else
{
((TableRow)e.Item).Cells[4].Text = String.Format("$ {0:c}", strRate.ToString() + ".00");
}
//--Est Total Column---//
xTotal = Decimal.Multiply( Decimal.Parse( strRate.ToString() ), Decimal.Parse(strEQ.ToString())).ToString() ;
dblVal = Math.Round( Decimal.Parse(xTotal.ToString()),2 );
((TableRow)e.Item).Cells[5].Text = String.Format("$ {0:c}",dblVal.ToString());
//--id column--//
strId = ((XmlElement)e.Item.DataItem).Attributes["id"].InnerText;
((TableRow)e.Item).Cells[7].Text = String.Format("{0:n}", strId.ToString());
//--total rollup--//
ViewState["sec2Total"] = Decimal.Add(Decimal.Parse( ViewState["sec2Total"].ToString() ), Decimal.Parse(xTotal.ToString())).ToString();
dblVal = Math.Round( Decimal.Parse(ViewState["sec2Total"].ToString()),2 );
this.lblSec2Total.Text = String.Format("$ {0:c}",ViewState["sec2Total"].ToString());
break;
default:
break;
}
}


private void DataGrid1_EditCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.Load(fileName);
//---//
Label lblCostDescr = new Label();
lblCostDescr.Text = ((TableRow)e.Item).Cells[1].Text;
//---//
Label lblCostEQ = new Label();
lblCostEQ.Text = ((TableRow)e.Item).Cells[2].Text;
//---//
Label lblCostUM= new Label();
lblCostUM.Text = ((TableRow)e.Item).Cells[3].Text;
//---//
Label lblCostRate= new Label();
lblCostRate.Text = ((TableRow)e.Item).Cells[4].Text;
string strTxt2Str = lblCostRate.Text;
strTxt2Str = strTxt2Str.Remove(strTxt2Str.IndexOf("$"),1);
lblCostRate.Text = strTxt2Str.Trim();
//---//
Label lblCostid= new Label();
lblCostid.Text = ((TableRow)e.Item).Cells[7].Text;
//---//
ViewState["xpathQuery"] = "\"/Section2/cost[@id='" + lblCostid.Text + "']\"";
//---//
this.DataGrid1.ShowFooter = false;
this.DataGrid1.EditItemIndex = e.Item.ItemIndex;
bindGrid();
}


private void DataGrid1_UpdateCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
if(e.Item.ItemIndex == this.DataGrid1.EditItemIndex)
{
XmlDocument doc = new XmlDocument();
doc.Load(fileName);
xpathQuery = ViewState["xpathQuery"].ToString();
//---Value given for the <cost> element
TextBox tbCostDescrEdit = new TextBox();
tbCostDescrEdit = (TextBox)e.Item.FindControl("tbCostDescrEdit");//
//XmlNode sNodeU = doc.SelectSingleNode("/Root/Section2/cost[@id='sc2-3']");
XmlNode sNodeU = null; //doc.SelectSingleNode("/Root/Section2/cost");
int iCostNode = 0;
XmlNodeList sNodeListU = doc.SelectNodes("/Root/Section2/cost");
foreach(XmlNode xNodeU in sNodeListU)
{
if(iCostNode == e.Item.ItemIndex) //If the index of the XmlNode == index of DataGrid Item...
{
sNodeU = xNodeU;
sNodeU.InnerText = tbCostDescrEdit.Text;
TextBox tbCostEQEdit = new TextBox();
tbCostEQEdit = (TextBox)e.Item.FindControl("tbCostEQEdit");//
sNodeU.Attributes["EQ"].InnerText = tbCostEQEdit.Text;
//---//
DropDownList ddlCostUMEdit = new DropDownList();
ddlCostUMEdit = (DropDownList)e.Item.FindControl("ddlCostUMEdit");//
sNodeU.Attributes["UM"].InnerText = ddlCostUMEdit.SelectedValue;
//---//
TextBox tbCostRateEdit = new TextBox();
tbCostRateEdit = (TextBox)e.Item.FindControl("tbCostRateEdit");
sNodeU.Attributes["Rate"].InnerText = tbCostRateEdit.Text;
break;
}
iCostNode++;
}
//---//
doc.Save(fileName);
DataGrid1.EditItemIndex = -1;
DataGrid1.ShowFooter = true;
bindGrid();
}
}

}
}



What Do You Think? :cool:

Now I'm working on replicating this code to subsequent pages and insuring that each page pulls up the correct section and cost tags from the file. The next thing I need to find out is what scripting I'm going to need to pass the XML file to a Crystal report.

My Thanks to PremiumBlend for Execellent assistants! Your 2 For 2 Buddy!:thumbsup: