How do I delete an entry from an XML file? - c#

I have the xml information populate in a listBox(lstAnimals). I can delete from the listBox with the following code:
private void btnAdopt_Click(object sender, EventArgs e)
{
DialogResult result = MessageBox.Show("Complete Adoption?", "Found a Happy Home!", MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
{
if (lstAnimals.SelectedIndex >= 0)
lstAnimals.Items.Remove(lstAnimals.SelectedItem);
}
else
{
return;
}
However, when the list is updated/program opened, that entry repopulates into the listBox. How can I delete this from the XML document simultaneously with the lixtBox?
Here is the xml:
<?xml version="1.0" encoding="UTF-8"?>
<Animals>
<Animal>
<Name>Bruce</Name>
<Type>Dog</Type>
<Age>Adult</Age>
</Animal>
<Animal>
<Name>Gizmo</Name>
<Type>Cat</Type>
<Age>Senior</Age>
</Animal>
</Animals>
I was asked how I populate my listBox, so here is the code:
private void UpdateList()
{
var an = XElement.Load(#"Animals.xml")
.Descendants("Animal")
.OrderBy(xe => (xe.Element("Name").Value))
.ToList<XElement>();
lstAnimals.Items.Clear();
foreach (var a in an)
lstAnimals.Items.Add(new Animal()
{
name = a.Element("Name").Value.ToString(),
type = a.Element("Type").Value,
age = a.Element("Age").Value
});
}
Picture of what the listBox presents as:
http://img.photobucket.com/albums/v84/Shades9323/shelterapp_zps4c22868c.jpg

Add this code into your button click event
string text = lstAnimals.SelectedItem.ToString();
string animalName = text.Substring(0, text.IndexOf("is")).Trim();
XDocument xDoc = XDocument.Load("Animals.xml"); //here is your filepath
XElement element = (from x in xDoc.Descendants("Animal")
where x.Element("Name").Value == animalName
select x).First();
element.Remove();
xDoc.Save("Animals.xml");
lstAnimals.Items.Remove(lstAnimals.SelectedItem);
Ofcourse if you add Id property to your animals,it will be easier.Just store id variable into your listBox Items "Tag" property..

You can use XmlDocument removeChild method similar to this
XmlDocument doc ;
doc = new XmlDocument();
doc.Load("path to your XML file");
XmlNode animalNode;
XmlNode root = doc.DocumentElement;
animalNode=root.SelectSingleNode("descendant::Animal[Name='" + lstAnimals.SelectedItem + "']");
doc.RemoveChild(animalNode) ;
//save the XML file

Here how you can do it using linq to xml
private void btnAdopt_Click(object sender, EventArgs e)
{
DialogResult result = MessageBox.Show("Complete Adoption?", "Found a Happy Home!", MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
{
if (lstAnimals.SelectedIndex >= 0)
{
lstAnimals.Items.Remove(lstAnimals.SelectedItem);
XDocument xDoc = XDocument.Load("test.xml");
xDoc.Descendants("Animal").Where(x => x.Element("Name").Value.ToString() == lstAnimals.SelectedItem ).Remove();
xDoc.Save("test1.xml");
}
}
else
{
return;
}

Related

How To Remove Last Node In XML? C#

I am trying to remove the last node from an XML file, but cannot find any good answers for doing this. Here is my code:
XmlReader x = XmlReader.Create(this.PathToSpecialFolder + #"\" + Application.CompanyName + #"\" + Application.ProductName + #"\Recent.xml");
int c = 0;
while (x.Read())
{
if (x.NodeType == XmlNodeType.Element && x.Name == "Path")
{
c++;
if (c <= 10)
{
MenuItem m = new MenuItem() { Header = x.ReadInnerXml() };
m.Click += delegate
{
};
openRecentMenuItem.Items.Add(m);
}
}
}
x.Close();
My XML node structure is as follows...
<RecentFiles>
<File>
<Path>Text Path</Path>
</File>
</RecentFiles>
In my situation, there will be ten nodes maximum, and each time a new one is added, the last must be removed.
You can try this
XmlDocument doc = new XmlDocument();
doc.Load(fileName);
XmlNodeList nodes = doc.SelectNodes("/RecentFiles/File");
nodes[nodes.Count].ParentNode.RemoveChild(nodes[nodes.Count]);
doc.Save(fileName);
It sounds like you want something like:
var doc = XDocument.Load(path);
var lastFile = doc.Descendants("File").LastOrDefault();
if (lastFile != null)
{
lastFile.Remove();
}
// Now save doc or whatever you want to do with it...

Failing To Parse the XML File in C#

I am a c++ developer and I started working on a C# WPF project. I have a method which should read the xml file. In my c++ application I could do it very efficiently but in WPF I am not sure how to approach the problem. Let me show you my code:
// When Browse Button is clicked this method is called
private void ExecuteScriptFileDialog()
{
var dialog = new OpenFileDialog { InitialDirectory = _defaultPath };
dialog.DefaultExt = ".xml";
dialog.Filter = "XML Files (*.xml)|*.xml";
dialog.ShowDialog();
ScriptPath = dialog.FileName; //ScriptPath contains the Path of the Xml File
if (File.Exists(ScriptPath))
{
LoadAardvarkScript(ScriptPath);
}
}
public void LoadAardvarkScript(string ScriptPath)
{
// I should read the xml file
}
I had achieved in C++ as follows:
File file = m_selectScript->getCurrentFile(); //m_selectScript is combobox name
if(file.exists())
{
LoadAardvarkScript(file);
}
void LoadAardvarkScript(File file)
{
XmlDocument xmlDoc(file);
//Get the main xml element
XmlElement *mainElement = xmlDoc.getDocumentElement();
XmlElement *childElement = NULL;
XmlElement *e = NULL;
int index = 0;
if(!mainElement )
{
//Not a valid XML file.
return ;
}
//Reading configurations...
if(mainElement->hasTagName("aardvark"))
{
forEachXmlChildElement (*mainElement, childElement)
{
//Read Board Name
if (childElement->hasTagName ("i2c_write"))
{
// Some code
}
}
}
How can I get the tagname of both mainElement and childelem as done in my c++ code? :)
not knowing the layout of your xml file here is an example that you can use if you know how to use Linq
class Program
{
static void Main(string[] args)
{
XElement main = XElement.Load(#"users.xml");
var results = main.Descendants("User")
.Descendants("Name")
.Where(e => e.Value == "John Doe")
.Select(e => e.Parent)
.Descendants("test")
.Select(e => new { date = e.Descendants("Date").FirstOrDefault().Value, points = e.Descendants("points").FirstOrDefault().Value });
foreach (var result in results)
Console.WriteLine("{0}, {1}", result.date, result.points);
Console.ReadLine();
}
}
you could also use XPATH as well to parse xml file.. but would really need to see the xml file layout
if you want to do it using xmlreader
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace XmlReading
{
class Program
{
static void Main(string[] args)
{
//Create an instance of the XmlTextReader and call Read method to read the file
XmlTextReader textReader = new XmlTextReader("C:\\myxml.xml");
textReader.Read();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(textReader);
XmlNodeList BCode = xmlDoc.GetElementsByTagName("Brandcode");
XmlNodeList BName = xmlDoc.GetElementsByTagName("Brandname");
for (int i = 0; i < BCode.Count; i++)
{
if (BCode[i].InnerText == "001")
Console.WriteLine(BName[i].InnerText);
}
Console.ReadLine();
}
}
}
Use LINQ queries to extract data from xml (XDocument)
Refer this link for further insights on XLinq.
Sample XML :
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<People>
<Person id="1">
<Name>Joe</Name>
<Age>35</Age>
<Job>Manager</Job>
</Person>
<Person id="2">
<Name>Jason</Name>
<Age>18</Age>
<Job>Software Engineer</Job>
</Person>
</People>
Sample Linq query:
var names = (from person in Xdocument.Load("People.xml").Descendants("Person")
where int.Parse(person.Element("Age").Value) < 30
select person.Element("Name").Value).ToList();
Names will be list of string. This query will return Jason as he is 18 yrs old.
Using Linq2Xml,
var xDoc = XDocument.Load("myfile.xml");
var result = xDoc.Descendants("i2c_write")
.Select(x => new
{
Addr = x.Attribute("addr").Value,
Count = x.Attribute("count").Value,
Radix = x.Attribute("radix").Value,
Value = x.Value,
Sleep = ((XElement)x.NextNode).Attribute("ms").Value
})
.ToList();
var khz = xDoc.Root.Element("i2c_bitrate").Attribute("khz").Value;

How to delete selected node from XML in C#?

I am New To C# I have problem...
I want to delete selected node from My XMl File
Here I just tried with this code but I didn't get please can any one help in that
private void btnDelete_Click(object sender, EventArgs e)
{
xdoc.Load(strFilename);
string Xpath = string.Format("root/{0}/{1}",_strProCat,_strProdType);
xdoc.SelectSingleNode(Xpath).RemoveAll();
xdoc.Save(strFilename);
MessageBox.Show("Deleted Successfully");
}
Here My Xml File
<root>
<product category="Soaps">
<product type="Washing">
<product name="Rin">
<Id>100</Id>
<AvailProducts>30</AvailProducts>
<Cost>20.00</Cost>
</product>
<product name="Tide">
<Id>101</Id>
<AvailProducts>30</AvailProducts>
<Cost>15.00</Cost>
</product>
</product>
</product>
</root>
Just I want to delete Node which product name="Tide"
You can simple use the below code:
private void btnDelete_Click(object sender, EventArgs e)
{
var xDoc = XDocument.Load(strFilename);
foreach (var elem in xDoc.Document.Descendants("product"))
{
foreach (var attr in elem.Attributes("name"))
{
if (attr.Value.Equals("Tide"))
elem.RemoveAll();
}
}
xDoc.Save(destinationFilename);
MessageBox.Show("Deleted Successfully");
}
Happy Coding...
Something like this should do it:
xdoc.Elements("product").Where(x=> x.Element("name").Value == "Tide").FirstOrDefault().Remove();
If you want XPath with XmlDocument then following is the way to do it..
XmlDocument xdoc = new XmlDocument();
xdoc.Load(strFilename);
string Xpath = string.Format("root/product[#category='{0}']/product[#type='{1}']/product[#name='{2}']", "Soaps", "Washing", "Tide");
xdoc.SelectSingleNode(Xpath).RemoveAll();
xdoc.Save(strFilename);
Update
As per your Requirement To Remove the empty node, try following code to remove empty node as
XmlNodeList emptyElements = xdoc.SelectNodes(#"//*[not(node())]");
for (int i = emptyElements.Count - 1; i > -1; i--)
{
XmlNode nodeToBeRemoved = emptyElements[i];
nodeToBeRemoved.ParentNode.RemoveChild(nodeToBeRemoved);
}
Now your final full flesh code will look like as
string Xpath = string.Format("root/product[#category='{0}']/product[#type='{1}']/product[#name='{2}']", "Soaps", "Washing", "Tide");
xdoc.SelectSingleNode(Xpath).RemoveAll();
XmlNodeList emptyElements = xdoc.SelectNodes(#"//*[not(node())]");
for (int i = emptyElements.Count - 1; i > -1; i--)
{
XmlNode nodeToBeRemoved = emptyElements[i];
nodeToBeRemoved.ParentNode.RemoveChild(nodeToBeRemoved);
}
xdoc.Save(strFilename);

Writing textbox values to xml file in C#.net

I have two TextBoxes namely txtUserid and txtPassowrd.
I'm writing the values entered in textboxes to a XML file but I do not want the same txtuserid values to be written twice in XML - it should be overwritten.
For example :
If I enter in txtUserid=2 and txtPassword=I
and the second time if I enter txtUserid=2 and txtPassword=m
then I only want one entry to be kept in the XML file :
For the above example: the txtUserid=2 and textPassword=m
The code:
XDocument Xdoc = new XDocument(new XElement("Users"));
if (System.IO.File.Exists("D:\\Users.xml"))
{
Xdoc = XDocument.Load("D:\\Users.xml");
}
else
{
Xdoc = new XDocument();
}
XElement xml = new XElement("Users",
new XElement("User",
new XAttribute("UserId", txtUserName.Text),
new XAttribute("Password", txtPassword.Text)));
if (Xdoc.Descendants().Count() > 0)
{
Xdoc.Descendants().First().Add(xml);
}
else
{
Xdoc.Add(xml);
}
Xdoc.Save("D:\\Users.xml");
Search your existing XML document for a node where the UserId attribute matches your current one, and if it does, modify that one, else make a new one.
I'd imagine that your coude would resemble the following:
List<XElement> list = Xdoc.Descendants("User").Where(el => el.Attribute("UserId").Value == txtUserName.Text).ToList();
if (list.Count == 0)
{
// Add new node
}
else
{
// Modify the existing node
}
Edit: In response to your comment, the code to edit your XElement would look something like
string myValue = "myValue";
list.First().Attribute("ElementName").SetValue(myValue);
Writing textbox values to XML file in C#
protected void btnSave_Click(object sender, EventArgs e)
{
// Open the XML doc
System.Xml.XmlDocument myXmlDocument = new System.Xml.XmlDocument();
myXmlDocument.Load(Server.MapPath("InsertData.xml"));
System.Xml.XmlNode myXmlNode = myXmlDocument.DocumentElement.FirstChild;
// Create new XML element and populate its attributes
System.Xml.XmlElement myXmlElement = myXmlDocument.CreateElement("entry");
myXmlElement.SetAttribute("Userid", Server.HtmlEncode(textUserid.Text));
myXmlElement.SetAttribute("Username", Server.HtmlEncode(textUsername.Text));
myXmlElement.SetAttribute("AccountNo", Server.HtmlEncode(txtAccountNo.Text));
myXmlElement.SetAttribute("BillAmount", Server.HtmlEncode(txtBillAmount.Text));
// Insert data into the XML doc and save
myXmlDocument.DocumentElement.InsertBefore(myXmlElement, myXmlNode);
myXmlDocument.Save(Server.MapPath("InsertData.xml"));
// Re-bind data since the doc has been added to
BindData();
Response.Write(#"<script language='javascript'>alert('Record inserted Successfully Inside the XML File....')</script>");
textUserid.Text = "";
textUsername.Text = "";
txtAccountNo.Text = "";
txtBillAmount.Text = "";
}
void BindData()
{
XmlTextReader myXmlReader = new XmlTextReader(Server.MapPath("InsertData.xml"));
myXmlReader.Close();
}

populate a tree view with an xml file

Im using .net windows form application. I have an xml file.I want to populate a tree view with data from a xml file. I am doing this using the following code.
private void button1_Click(object sender, EventArgs e)
{
try
{
this.Cursor = System.Windows.Forms.Cursors.WaitCursor;
//string strXPath = "languages";
string strRootNode = "Treeview Sample";
OpenFileDialog Dlg = new OpenFileDialog();
Dlg.Filter = "All files(*.*)|*.*|xml file (*.xml)|*.txt";
Dlg.CheckFileExists = true;
string xmlfilename = "";
if (Dlg.ShowDialog() == DialogResult.OK)
{
xmlfilename = Dlg.FileName;
}
// Load the XML file.
//XmlDocument dom = new XmlDocument();
//dom.Load(xmlfilename);
XmlDocument doc = new XmlDocument();
doc.Load(xmlfilename);
string rootName = doc.SelectSingleNode("/*").Name;
textBox4.Text = rootName.ToString();
//XmlNode root = dom.LastChild;
//textBox4.Text = root.Name.ToString();
// Load the XML into the TreeView.
this.treeView1.Nodes.Clear();
this.treeView1.Nodes.Add(new TreeNode(strRootNode));
TreeNode tNode = new TreeNode();
tNode = this.treeView1.Nodes[0];
XmlNodeList oNodes = doc.SelectNodes(textBox4.Text);
XmlNode xNode = oNodes.Item(0).ParentNode;
AddNode(ref xNode, ref tNode);
this.treeView1.CollapseAll();
this.treeView1.Nodes[0].Expand();
this.Cursor = System.Windows.Forms.Cursors.Default;
}
catch (Exception ex)
{
this.Cursor = System.Windows.Forms.Cursors.Default;
MessageBox.Show(ex.Message, "Error");
}
}
private void AddNode(ref XmlNode inXmlNode, ref TreeNode inTreeNode)
{
// Recursive routine to walk the XML DOM and add its nodes to a TreeView.
XmlNode xNode;
TreeNode tNode;
XmlNodeList nodeList;
int i;
// Loop through the XML nodes until the leaf is reached.
// Add the nodes to the TreeView during the looping process.
if (inXmlNode.HasChildNodes)
{
nodeList = inXmlNode.ChildNodes;
for (i = 0; i <= nodeList.Count - 1; i++)
{
xNode = inXmlNode.ChildNodes[i];
inTreeNode.Nodes.Add(new TreeNode(xNode.Name));
tNode = inTreeNode.Nodes[i];
AddNode(ref xNode, ref tNode);
}
}
else
{
inTreeNode.Text = inXmlNode.OuterXml.Trim();
}
}
My xml file is this:"hello.xml"
<?xml version="1.0" encoding="utf-8" ?>
<languages>
<language>
<key>abc</key>
<value>hello how ru</value>
</language>
<language>
<key>def</key>
<value>i m fine</value>
</language>
<language>
<key>ghi</key>
<value>how abt u</value>
</language>
</languages>
Now after using the above code I am able to populate the tree view. But I dont like to populate the complete xml file. I should get only till
languages
language
key
value
I don't want
abc
how are you
etc.....
I mean to say the leaf nodes. Please help me
What you don't want to add is the text content of the nodes, if I understood correctly; then, you might check the NodeType property of the XmlNode class, something like:
xNode = inXmlNode.ChildNodes[i];
if (xNode.NodeType != XmlNodeType.Text) {
inTreeNode.Nodes.Add(new TreeNode(xNode.Name));
tNode = inTreeNode.Nodes[i];
AddNode(ref xNode, ref tNode);
}

Categories