How to append data to existing xml? - c#

I have this xml file called "list.xml".
<?xml version="1.0" encoding="utf-8" ?>
<PeopleList>
<Person>
<First-Name>John</First-Name>
<Last-Name>Sims</Last-Name>
<Address-1>214,NJ Lane</Address-1>
<Address-2>Ney York</Address-2>
<Post-Code>8000</Post-Code>
<City>NJ</City>
</Person>
<Person>
<First-Name>Arya</First-Name>
<Last-Name>Stark</Last-Name>
<Address-1>214,Latin Street</Address-1>
<Address-2>Los Angeles</Address-2>
<Post-Code>302</Post-Code>
<City>CA</City>
</Person>
<Person>
<First-Name>Rick</First-Name>
<Last-Name>Rider</Last-Name>
<Address-1>500,LA Lane</Address-1>
<Address-2>Miami</Address-2>
<Post-Code>768</Post-Code>
<City>LA</City>
</Person>
</PeopleList>
How can I append following data to the above xml?
<Person>
<First-Name>Test User 1</First-Name>
<Last-Name>Test Last Name</Last-Name>
<Address-1>Test add 1</Address-1>
<Address-2>Test add 2</Address-2>
<Post-Code>Test Post code</Post-Code>
<City>Test City</City>
</Person>
Is this the correct way?
XmlDocument xd = new XmlDocument();
xd.Load("list.xml");
XmlNode nl = xd.SelectSingleNode("//Person");
XmlDocument xd2 = new XmlDocument();
xd2.LoadXml("<Person><First-Name>20</First-Name>....</Person>");
XmlNode n = xd.ImportNode(xd2.FirstChild,true);
nl.AppendChild(n);

You can use LINQ to XML
var newElement = new XElement("Person",
new XElement("First-Name", "Test User 1"),
new XElement("Last-Name", "Test Last Name"),
new XElement("Address-1", "Test add 1"),
new XElement("Address-2", "Test add 2"),
new XElement("Post-Code", "Test Post code"),
new XElement("City", "Test City")
);
var xDoc = XDocument.Load("path");
xDoc.Root.Add(newElement);
xDoc.Save(path);
See the documentation for more details: XContainer.Add Method

Related

C# XML Read All Child Nodes Of A Specific Node

So I have a program that reads all the name nodes in a XML file and adds these to a Combo Box. On a button click, it then takes this response and needs to get all the other data from the child nodes of the node the name is in.
The XML document:
<People>
<Person>
<Name>Greg</Name>
<Age>23</Age>
<Height>200</Height>
</Person>
<Person>
<Name>John</Name>
<Age>34</Age>
<Height>230</Height>
</Person>
</People>
What I've got so far:
XmlDocument Doc = new XmlDocument();
Doc.Load(FilePath);
foreach (XmlNode Node in Doc.SelectNodes("People/Person"))
{
comboBox1.Items.Add(Node.SelectSingleNode("Name").InnerText);
}
string RegPicked = comboBox1.SelectedItem.ToString();
foreach (XmlNode xNode in Doc.SelectNodes("People/Person"))
if (xNode.SelectSingleNode("Name").InnerText == RegPicked)
{
textBox1.Text = xNode.ParentNode.ChildNodes.ToString();
}
Doc.Save(FilePath);
When I run the code I just get "System.Xml.XmlChildNodes" in the text box.
I know I've done something wrong but I'm not sure what.
you have to distinguished child node:
textBox1.Text = xNode.ParentNode.ChildNodes.SelectSingleNode("age").InnerText;
Do this, you will get all the elements inside the parent of the node you are searching the value of.
string str = #"<People>
<Person>
<Name>Greg</Name>
<Age>23</Age>
<Height>200</Height>
</Person>
<Person>
<Name>John</Name>
<Age>34</Age>
<Height>230</Height>
</Person>
</People>";
XDocument xdoc = XDocument.Parse(str);
var xmlURL = (from el in xdoc.Descendants("Name")
where el.Value == "John"
select el.Parent).First().ToString();

validating an xml and finding line and column of error

i have an xml document of this kind
<xml>
<person name="a">
<age>21</age>
<salary>50000></salary>
</person>
<person name="b">
<age>25</age>
<salary>30000></salary>
</person>
<person name="c">
<age>30</age>
<salary>60000></salary>
</person>
<person name="d">
<age>35</age>
<salary>150000></salary>
</person>
</xml>
Now im trying to validate this document by passing this to a method like this
validate(string file)
{
// here i have some logic
// say i am trying to check if the salary is >50000 and age > 30
// if it doesn't satisfy the condition i have to return an error
}
I am able to achieve this . What i really want is to know where exactly the error in xml document is , like which line and column.
How should i do this ? any suggestions?
You are closing your 'age' tag like this
<age>35<age/>
It should be like
<age>35</age>
hope this works for you.
Firstly, you have not specified how you are parsing your XML in c#. It matters.
Now as for validity of your XML document, a valid xml document should have these:
XML documents must have a root element
XML elements must have a closing tag
XML tags are case sensitive
XML elements must be properly nested
-XML attribute values must be quoted
now try adding this to the top of your xml doc
<?xml version="1.0" encoding="ISO-8859-1"?>
Now, to parse XML document, you can use either XmlDocument class or Linq's XDocument class.
Lets take example of XmlDocument.
if you have a xml string, load Xml as below:
XmlDocument doc = new XmlDocument();
doc.LoadXml(stringXML);
foreach(XmlNode node in doc.SelectNodes("xml/person/salary"))
{
var strSalary = node.InnerText;
var intSalary = Convert.ToInt32(strSalary??0);
}
if you have a xml file, load Xml as below:
XmlDocument doc = new XmlDocument();
doc.Load(XMLFilePath);
Full example:
string xml = #"<xml>
<person name=""a"">
<age>21</age>
<salary>50000</salary>
</person>
<person name=""b"">
<age>25</age>
<salary>30000</salary>
</person>
<person name=""c"">
<age>30</age>
<salary>60000</salary>
</person>
<person name=""d"">
<age>35</age>
<salary>150000</salary>
</person>
</xml>";
using (var sr = new StringReader(xml))
{
var xml2 = XDocument.Load(sr, LoadOptions.SetLineInfo);
foreach (var person in xml2.Root.Elements())
{
//string name = (string)person.Attribute("name"); // Unused
int age = (int)person.Element("age");
int salary = (int)person.Element("salary");
// Your check
bool error = salary > 50000 && age > 30;
if (error)
{
// IMPORTANT PART HERE!!!
int lineNumber = -1;
int colNumber = -1;
var lineInfo = (IXmlLineInfo)person;
if (lineInfo.HasLineInfo())
{
lineNumber = lineInfo.LineNumber;
colNumber = lineInfo.LinePosition;
}
return string.Format("Error on line {0}, col {1}", lineNumber, colNumber);
// END IMPORTANT PART!!!
}
}
}
The "trick" is that XElement implement IXmlLineInfo (as explained here), but you have to load the document with LoadOptions.SetLineInfo.

xml error:System.Xml.XPath.XPathException: Expression must evaluate to a node-set

I am trying to find a node in my xml file but getting the error ( see title)?
// instantiate XmlDocument and load XML from file
XmlDocument doc = new XmlDocument();
doc.Load(#"C:\temp\test2.xml");
var node = doc.SelectSingleNode("/Offers/Offer/ID=[text()='1']");
var test = node;
xml
<?xml version="1.0" encoding="utf-8"?>
<Offers>
<Offer>
<Model>AAAA</Model>
<ID>1</ID>
<Name>First offer</Name>
</Offer>
<Offer>
<Model>BBBB</Model>
<ID>2</ID>
<Name>Second offer</Name>
</Offer>
</Offers>
Remove the = after ID:
var node = doc.SelectSingleNode("/Offers/Offer/ID=[text()='1']");
becomes:
var node = doc.SelectSingleNode("/Offers/Offer/ID[text()='1']");

Adding data to XML file

My XML file is:
<?xml version="1.0" encoding="utf-8" ?>
<people>
<person
index="1"
name="Zlecenie numer jeden"
beneficiary="Kowalski"
description="Proste zlecenie jakiejs strony czy cos"
price="800"
deadline="27.12.2013" />
</people>
How can I add to this existing file, something like new record:
<person
index="4"
name="Zlecenie numer cztery"
beneficiary="Kowalski"
description="Proste zlecenie jakiejs strony czy cos"
price="800"
deadline="27.12.2013" />
or remove or if you know how to update existing record then this too. Thanks
Try the next code snippet for adding element into xml. Note that I've used xml as string with escaped characters. You probably have xml file
var str = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n<people>\r\n<person\r\nindex=\"1\"\r\nname=\"Zlec" +
"enie numer jeden\"\r\nbeneficiary=\"Kowalski\"\r\ndescription=\"Proste zlecenie jakiejs " +
"strony czy cos\"\r\nprice=\"800\"\r\ndeadline=\"27.12.2013\" />\r\n</people>";
var xml = XElement.Parse(str);
var newNode = new XElement("person",
new XAttribute("index", 4),
new XAttribute("name", "Zlecenie numer cztery"),
new XAttribute("beneficiary", "Kowalski"),
new XAttribute("description", "Proste zlecenie jakiejs strony czy cos"),
new XAttribute("price", 800),
new XAttribute("deadline", "27.12.2013"));
xml.Add(newNode);
//you can store whole xml tree in one variable simply by calling ToString on xml
str = xml.Tostring();
Console.WriteLine(str);
Prints:
<people>
<person index="1" name="Zlecenie numer jeden" beneficiary="Kowalski" description="Proste zlecenie jakiejs strony czy cos" price="800" deadline="27.12.2013" />
<person index="4" name="Zlecenie numer cztery" beneficiary="Kowalski" description="Proste zlecenie jakiejs strony czy cos" price="800" deadline="27.12.2013" />
</people>
XDocument xdoc = XDocument.Load(xmlFileName);
void Update(XDocument xdoc )
{
XElement repser = doc.Root.Element("people").Elements("person").Where(r => (int)r.Attribute("index") = xdoc.index).FirstOrDefault();
if (repser != null)
{
// update
repser.SetAttribute("name", xdoc.name);
repser.SetAttribute("beneficiary", xdoc.beneficiary);
repser.SetAttribute("description", xdoc.description);
repser.SetAttribute("price", xdoc.price);
repser.SetAttribute("deadline", xdoc.deadline);
// and so on
}
else
{
//insert
doc.Root.Element("people").Add
new XElement("person",
new XAttribute("index", xdoc.id),
new XAttribute("name", xdoc.name),
new XAttribute("beneficiary", xdoc.beneficiary),
new XAttribute("description", xdoc.description),
new XAttribute("price", xdoc.price),
new XAttribute("deadline", xdoc.deadline)
// and so on
));
}
}
You can manually plug in the values in the XAttribute values in the else statement for the update.

how can append to xml

i have this xml.
<project>
<user>
<id>1</id>
<name>a</name>
</user>
<user>
<id>2</id>
<name>b</name>
</user>
</project>
now how can append a new element like this between element <project></project>
<user>
<id>3</id>
<name>c</name>
</user>
string xml =
#"<project>
<user>
<id>1</id>
<name>a</name>
</user>
<user>
<id>2</id>
<name>b</name>
</user>
</project>";
XElement x = XElement.Load(new StringReader(xml));
x.Add(new XElement("user", new XElement("id",3),new XElement("name","c") ));
string newXml = x.ToString();
If you mean using C# then probably the simplest way is to load the xml up into an XmlDocument object and then add a node representing the additional element.
e.g. something like:
string filePath = "original.xml";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(filePath);
XmlElement root = xmlDoc.DocumentElement;
XmlNode nodeToAdd = doc.CreateElement(XmlNodeType.Element, "user", null);
XmlNode idNode = doc.CreateElement(XmlNodeType.Element, "id", null);
idNode.InnerText = "1";
XmlNode nameNode = doc.CreateElement(XmlNodeType.Element, "name", null);
nameNode.InnerText = "a";
nodeToAdd.AppendChild(idNode);
nodeToAdd.AppendChild(nameNode);
root.AppendChild(nodeToAdd);
xmlDoc.Save(filePath); // Overwrite or replace with new file name
But you haven't said where the xml fragments are - in files/strings?
If you have the below XML file:
<CATALOG>
<CD>
<TITLE> ... </TITLE>
<ARTIST> ... </ARTIST>
<YEAR> ... </YEAR>
</CD>
</CATALOG>
and you have to add another <CD> node with all its child nodes:
using System.Xml; //use the xml library in C#
XmlDocument document = new XmlDocument(); //creating XML document
document.Load(#"pathOfXmlFile"); //load the xml file contents into the newly created document
XmlNode root = document.DocumentElement; //points to the root element (catalog)
XmlElement cd = document.CreateElement("CD"); // create a new node (CD)
XmlElement title = document.CreateElement("TITLE");
title.InnerXML = " ... "; //fill-in the title value
cd.AppendChild(title); // append title to cd
XmlElement artist = document.CreateElement("ARTIST");
artist.InnerXML = " ... ";
cd.AppendChild(artist);
XmlElement year = document.CreateElement("YEAR");
year.InnerXML = " ... ";
cd.AppendChild(year);
root.AppendChild(cd); // append cd to the root (catalog)
document.save(#"savePath");//save the document

Categories