Appending an existing XML file with XmlWriter
Solution 1
finally I succeeded :)
if (!File.Exists("Test.xml"))
{
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Indent = true;
xmlWriterSettings.NewLineOnAttributes = true;
using (XmlWriter xmlWriter = XmlWriter.Create("Test.xml", xmlWriterSettings))
{
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("School");
xmlWriter.WriteStartElement("Student");
xmlWriter.WriteElementString("FirstName", firstName);
xmlWriter.WriteElementString("LastName", lastName);
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
xmlWriter.Flush();
xmlWriter.Close();
}
}
else
{
XDocument xDocument = XDocument.Load("Test.xml");
XElement root= xDocument.Element("School");
IEnumerable<XElement> rows = root.Descendants("Student");
XElement firstRow= rows.First();
firstRow.AddBeforeSelf(
new XElement("Student",
new XElement("FirstName", firstName),
new XElement("LastName", lastName)));
xDocument.Save("Test.xml");
}
Solution 2
you can use Linq Xml
XDocument doc = XDocument.Load(xmlFilePath);
XElement school = doc.Element("School");
school.Add(new XElement("Student",
new XElement("FirstName", "David"),
new XElement("LastName", "Smith")));
doc.Save(xmlFilePath);
Edit
if you want to add Element to Existing <Student>
, just add an Attribute before
school.add(new XElement("Student",
new XAttribute("ID", "ID_Value"),
new XElement("FirstName", "David"),
new XElement("LastName", "Smith")));
Then you can add further Details to the Existing <Student>
by search -> get -> add
XElement particularStudent = doc.Element("School").Elements("Student")
.Where(student => student.Attribute("ID").Value == "SearchID")
.FirstOrDefault();
if(particularStudent != null)
particularStudent.Add(new XElement("<NewElementName>","<Value>");
Solution 3
Let me give you a suggestion. When you creating your xml file, give an unique id to your students like this:
// to store the id variable, if you create more than one student you can increase it
count = 0;
xmlWriter.WriteStartElement("School");
xmlWriter.WriteAttributeString("ID",count.ToString());
xmlWriter.WriteEndElement();
Then when you need to add information to this student you can get ID
,Firstname
and Lastname
and you can edit your XML file with LINQ to XML like this:
int id = Convert.ToInt32(txtStudentId.Text);
XDocument xDoc = XDocument.Load("Test.xml");
XElement student = xDoc.Descendants("Student").Where(x => (string) x.Attribute("ID") == id).FirstOrDefault();
if (student != null)
{
string firstName = txtFirstName.Text;
string lastName = txtLastName.Text;
XElement first = new XElement("FirstName", firstName);
XElement last = new XElement("LastName", lastName);
student.Add(first);
student.Add(last);
xDoc.Save("Test.xml");
}
Solution 4
I have a suggestion for the next time:
string nameFile = "Test.xml";
bool newFile = false;
if (!File.Exists(nameFile))
{
newFile = true;
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Indent = true;
xmlWriterSettings.NewLineOnAttributes = true;
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("School");
xmlWriter = XmlWriter.Create("Test.xml", xmlWriterSettings))
}
else
{
doc = new XmlDocument();
doc.Load(nameFile);
// Create a XPathNavigator
// You can go where you want to add
// In this case it is just after last child of the roor
XPathNavigator navigator = doc.CreateNavigator();
navigator.MoveToChild("School", "");
xmlWriter = navigator.AppendChild();
}
// From here you can work only with xmlWriter,
// One will point on a file and the other on the stream of xmlDocument
// So you will need to save the document in the second choise
xmlWriter.WriteStartElement("Student");
xmlWriter.WriteElementString("FirstName", firstName);
xmlWriter.WriteElementString("LastName", lastName);
xmlWriter.WriteEndElement();
// End document / close or save.
if (newFile)
xmlWriter.WriteEndDocument();
xmlWriter.Close();
if (!newFile)
doc.Save(nameFile);
It should work. :)
Solution 5
I know you asked for XmlWriter, but I believe you can achieve this using less code with XDocument. Here is my solution:
var filePath = "path/XmlFile.xml";
var xmlDoc = XDocument.Load(filePath);
var parentElement = new XElement("Student");
var firstNameElement = new XElement("FirstName", firstNameVariable);
var lastNameElement = new XElement("LastName", lastNameVariable);
parentElement.Add(firstNameElement);
parentElement.Add(lastNameElement);
var rootElement = xmlDoc.Element("School");
rootElement?.Add(parentElement);
xmlDoc.save();
This is based on the following XML structure and will append at ...
:
<School>
<Student>
<FirstName>John</FirstName>
<LastName>Johnson</LastName>
</Student>
...
</School>
Hope this helps!
user3105160
Updated on August 02, 2022Comments
-
user3105160 over 1 year
I've used the following code to create an XML file:
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings(); xmlWriterSettings.Indent = true; xmlWriterSettings.NewLineOnAttributes = true; using (XmlWriter xmlWriter = XmlWriter.Create("Test.xml", xmlWriterSettings)) { xmlWriter.WriteStartDocument(); xmlWriter.WriteStartElement("School"); xmlWriter.WriteEndElement(); xmlWriter.WriteEndDocument(); xmlWriter.Close(); }
I need to insert nodes dynamically creating the following structure:
<?xml version="1.0" encoding="utf-8"?> <School /> <Student> <FirstName>David</FirstName> <LastName>Smith</LastName> </Student> ... <Teacher> <FirstName>David</FirstName> <LastName>Smith</LastName> </Teacher> ... </School>
How can I do it? The values of "FirstName" and "LastName" should be read from the keyboard and the values can be entered at any time, of course under existing.
-
Selman Genç over 10 yearsbut your code creating a new element.OP want to add new elements to the existing element
-
user3105160 over 10 yearsexactly. I want to add new elements every time I need it
-
user3105160 over 10 yearsI'm sorry but I'm confused. It's the first time that use XML.
-
user3105160 over 10 yearsindeed :) thank you for the help and if you help me to complete this step I would be very grateful ;)
-
Banshee almost 9 yearsXDocument will read the entire file into memory, that not always a problem but it should be known.