Create/delete element on XMLNode c# - c#

It's my fist time working with XML and I use a basic XML file format like this:
<root>
<staff id="1">
<name>name 1</name>
<phone>123456</phone>
</staff>
<staff id="2">
<name>name 2</name>
<phone>123789</phone>
<phone2>123789</phone2>
</staff>
</root>
some nodes have more elements (phone2 in this case). I want to add (or remove) an element on a node. I'm creating a WinForms in C# that work with this XML. I'm doing:
I read the XML to have a XmlNodeList variable.
From XmlNodeList I get the node that I want modify to a XmlNode variable.
I modify name or phone on XmlNode
I read again the XML file and I update the correct node with the XmlNode variable new info.
My problem is I don't know how add (or remove) the element "phone2" on my XmlNode variable.
program.cs:
public static XmlNode staff;
public static XmlNodeList xnList = GetList();
public static XmlNodeList GetList()
{
XmlNodeList xnList;
XmlDocument doc = new XmlDocument();
doc.Load(path);
xnList = doc.SelectNodes("/root/staff");
return xnList;
}
public static void GetID(string id)
{
foreach (XmlNode xn in xnList)
{
if(xn.Attributes["id"].Value == id)
{
staff = xn;
}
}
}
form1.cs
private void btnOK_Click(object sender, EventArgs e)
{
Program.staff["name"].InnerText = textBoxName.Text;
Program.staff["phone"].InnerText = textBoxPhone.Text;
if (Program.staff.SelectSingleNode("phone2") == null)
{
// here I want to create "phone2" in Program.staff if not exist
// to update XML file later.
Program.staff["phone2"].InnerText = textBoxPhone2.Text;
}
}
I don't find the correct method to do it and maybe it's not the best way to do it, but I accept suggestions...

There are multiple ways to work with XML files. I'll show two options below.
Test.xml:
<root>
<staff id="1">
<name>Name 1</name>
<phone>123456</phone>
</staff>
<staff id="2">
<name>Name 2</name>
<phone>123457</phone>
<phone>123458</phone>
</staff>
</root>
Option 1 (LINQ to XML):
Add the following using directive:
using System.Xml.Linq;
CreateXmlLinq:
private void CreateXmlLinq(string filename)
{
XElement root = new XElement("root",
new XElement("staff", new XAttribute("id", "1"),
new XElement("name", "Name 1"),
new XElement("phone", "123456")),
new XElement("staff", new XAttribute("id", "2"),
new XElement("name", "Name 2"),
new XElement("phone", "123457"),
new XElement("phone", "123458"))
);
root.Save(filename);
}
Usage:
using (SaveFileDialog sfd = new SaveFileDialog())
{
sfd.Filter = "XML File (*.xml)|*.xml";
sfd.FileName = "Test.xml";
if (sfd.ShowDialog() == DialogResult.OK)
{
//save to file
CreateXmlLinq(sfd.FileName);
Debug.WriteLine($"Info: Saved to {sfd.FileName}");
}
}
To remove phone number 123458 where staff id = 2:
RemovePhone:
private void RemovePhone(string filename, string id, string phoneNumber)
{
//load from file
XElement root = XElement.Load(filename);
//remove specified phone number
root.Elements("staff").Where(s => s.Attribute("id").Value == id).Elements("phone").Where(p => p.Value == phoneNumber).Remove();
//save to file
root.Save(filename);
}
Option 2 (XML Serialization):
For this approach, we'll use nested classes.
Add the following using directives to each of the classes:
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
You can name the classes whatever you like, I've chosen to prepend the word "Xml". Additionally for the nested classes, I've chosen to append the ancestors' names. In this case, there is only one ancestor (the parent) "root".
XmlRoot
XmlRootStaff: ("XmlRoot" + "Staff)
XmlRoot.cs:
[XmlRoot(ElementName = "root", IsNullable = false)]
public class XmlRoot
{
[XmlElement(ElementName = "staff")]
public List<XmlRootStaff> Staff { get; set; } = new List<XmlRootStaff>();
}
XmlRootStaff.cs:
public class XmlRootStaff
{
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
[XmlElement(ElementName = "name")]
public string Name { get; set; }
[XmlElement(ElementName = "phone")]
public List<string> Phone { get; set; } = new List<string>();
}
To deserialize the XML (read from file) we'll use the following method:
DeserializeXMLFileToObject:
public static T DeserializeXMLFileToObject<T>(string xmlFilename)
{
T rObject = default(T);
try
{
if (string.IsNullOrEmpty(xmlFilename))
{
return default(T);
}
using (System.IO.StreamReader xmlStream = new System.IO.StreamReader(xmlFilename))
{
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
rObject = (T)serializer.Deserialize(xmlStream);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Error (DeserializeXMLFileToObject) - {ex.Message}");
throw;
}
return rObject;
}
Usage (deserialize):
private XmlRoot _root = null;
...
using (OpenFileDialog ofd = new OpenFileDialog())
{
ofd.Filter = "XML File (*.xml)|*.xml";
ofd.FileName = "Test.xml";
if (ofd.ShowDialog() == DialogResult.OK)
{
//deserialize
_root = HelperXml.DeserializeXMLFileToObject<XmlRoot>(ofd.FileName);
}
}
To serialize the XML (write to file) we'll use the following method:
SerializeObjectToXMLFile:
public static void SerializeObjectToXMLFile(object obj, string xmlFilename)
{
try
{
if (string.IsNullOrEmpty(xmlFilename))
{
return;
}//if
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings();
settings.OmitXmlDeclaration = false;
settings.Indent = true;
settings.NewLineHandling = System.Xml.NewLineHandling.Entitize;
using (System.Xml.XmlWriter xmlWriter = System.Xml.XmlWriter.Create(xmlFilename, settings))
{
//specify namespaces
System.Xml.Serialization.XmlSerializerNamespaces ns = new System.Xml.Serialization.XmlSerializerNamespaces();
ns.Add(string.Empty, "urn:none");
//create new instance
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(obj.GetType());
//write XML to file
serializer.Serialize(xmlWriter, obj, ns);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Error (SerializeObjectToXMLFile) - {ex.Message}");
throw;
}
}
Usage (serialize):
private XmlRoot _root = null;
...
using (SaveFileDialog sfd = new SaveFileDialog())
{
sfd.Filter = "XML File (*.xml)|*.xml";
sfd.FileName = "Test.xml";
if (sfd.ShowDialog() == DialogResult.OK)
{
//create new instance
_root = new XmlRoot();
//add data
_root.Staff.Add(new XmlRootStaff() { Id = "1", Name = "Name 1", Phone = new List<string>() { "123456" } });
_root.Staff.Add(new XmlRootStaff() { Id = "2", Name = "Name 2", Phone = new List<string>() { "123457", "123458" } });
//serialize - save to file
SerializeObjectToXMLFile(_root, sfd.FileName);
Debug.WriteLine($"Info: Saved to {sfd.FileName}");
}
}
To remove phone number 123458 where staff id = 2:
private void RemovePhone(string id, string phoneNumber)
{
if (_root != null)
{
for (int i = 0; i < _root.Staff.Count; i++)
{
if (_root.Staff[i].Id == id)
{
//remove
_root.Staff[i].Phone.Remove(phoneNumber);
break;
}
}
}
}
Resources:
LINQ to XML overview
XElement.Save Method
How to delete specific nodes from an XElement?
XML serialization
Examples of XML Serialization

Finally I solved changing:
program.cs
public static XmlDocument doc = new XmlDocument(); // ADDED THIS HERE
public static XmlNode staff;
public static XmlNodeList xnList = GetList();
public static XmlNodeList GetList()
{
XmlNodeList xnList;
// REMOVED XmlDocument from HERE
doc.Load(path);
xnList = doc.SelectNodes("/root/staff");
return xnList;
}
public static void GetID(string id)
{
foreach (XmlNode xn in xnList)
{
if(xn.Attributes["id"].Value == id)
{
staff = xn;
}
}
}
form1.cs
private void btnOK_Click(object sender, EventArgs e)
{
Program.staff["name"].InnerText = textBoxName.Text;
Program.staff["phone"].InnerText = textBoxPhone.Text;
if (Program.staff.SelectSingleNode("phone2") == null)
{
XmlElement elem = Program.doc.CreateElement("phone2");
elem.InnerText = textBoxPhone2.Text;
Program.staff.AppendChild(elem);
}
}

Related

Construction xml file: This document already has a ' DocumentElement ' node

I am trying to construct a .xml file of the form
<Orders>
<Id type="System.Int32">1</Id>
<OrderItems>
<OrderItem>
<Id type="System.Int32">321</Id>
<Product type="System.String">Coffee</Product>
</OrderItem>
</OrderItems>
<Client type="System.String">Johnny</Client>
<Orders>
For Order model:
public class Order
{
public int Id { get; set; }
public List<OrderItem> Products { get; set; }
public string Client { get; set; }
}
Here, I create the Order element
public void SaveToFile(IEnumerable<Order> elementsList)
{
XmlDocument xmlDoc = new XmlDocument();
XmlDeclaration xmlDec = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", string.Empty);
xmlDoc.PrependChild(xmlDec);
XmlElement elemRoot = xmlDoc.CreateElement("Orders");
xmlDoc.AppendChild(elemRoot);
XmlHelper<Order> xmlHelper = new XmlHelper<Order>();
foreach (var order in _orders)
{
xmlHelper.AddNodeToXmlDocument(xmlDoc, elemRoot, order);
}
xmlDoc.PreserveWhitespace = true;
xmlDoc.Save(_filePath);
}
And here, I am trying to construct the sub-elements. It works fine for Id and Client, but when I try to create the order items, I get this error at line document.AppendChild(elemRoot);
public void AddNodeToXmlDocument(XmlDocument document, XmlElement rootElement, object myObject)
{
XmlElement myObjectElement = document.CreateElement(EntityFormatter.GetObjectName(myObject));
foreach (var objectProperty in EntityFormatter.GetPropertiesAndValues(myObject))
{
if ((objectProperty.Value.GetType().FullName).ToString().Contains("System.Collections.Generic.List"))
{
Regex regex = new Regex(#"Models[.][A-Za-z]+");
Match match = regex.Match(objectProperty.Value.ToString());
var elemRoot = document.CreateElement(match.Value.Substring(7));
document.AppendChild(elemRoot);
foreach (var obj in objectProperty.Value.ToString())
{
AddNodeToXmlDocument(document, elemRoot, obj);
}
}
else
{
var elem = document.CreateElement(objectProperty.Key);
elem.SetAttribute("type", objectProperty.Value.GetType().FullName);
elem.InnerText = objectProperty.Value.ToString();
myObjectElement.AppendChild(elem);
}
}
rootElement.AppendChild(myObjectElement);
}
XML specification only allows single root element in a document. document.AppendChild(elemRoot) line in your AddNodeToXmlDocument() method throws exception because root element has been created before in the SaveToFile() method :
.....
XmlElement elemRoot = xmlDoc.CreateElement("Orders");
xmlDoc.AppendChild(elemRoot);
.....
It isn't clear what you're trying to do with the erroneous line, maybe you want to append elemRoot to the previously created root element instead :
.....
var elemRoot = document.CreateElement(match.Value.Substring(7));
document.DocumentElement.AppendChild(elemRoot);
.....

C# - parse xml nodes

I am loading my data from XML using C# this way:
XmlDocument xmlDoc = new XmlDocument();
TextAsset xmlFile = Resources.Load("levels/" + levelID) as TextAsset;
xmlDoc.LoadXml(xmlFile.text);
XmlNodeList levelsList = xmlDoc.GetElementsByTagName("level");
foreach (XmlNode levelInfo in levelsList)
{
XmlNodeList childNodes = levelInfo.ChildNodes;
foreach (XmlNode value in childNodes)
{
switch (value.Name)
{
case "info":
//levelWidth = getInt(value, 0);
//levelHeight = getInt(value, 1);
break;
}
}
}
And heres XML I am loading:
<?xml version="1.0" encoding="utf-8" ?>
<level>
<info w="1000" h="500"/>
</level>
It works just fine, I am now trying to find best way to load child nodes, inside my level node with multiple points nodes inside
<?xml version="1.0" encoding="utf-8" ?>
<level>
<info w="1000" h="500"/>
<ground>
<point val1="val1" val2="val2"/>
</ground>
</level>
I will be grateful for some guidance how to move in the right direction, thank you.
Using XML Linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string xml =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>" +
"<level>" +
"<info w=\"1000\" h=\"500\"/>" +
"</level>";
XDocument doc = XDocument.Parse(xml);
XElement level = (XElement)doc.FirstNode;
level.Add("ground", new object[] {
new XElement("point", new XAttribute[] {
new XAttribute("val1", "val1"),
new XAttribute("val2", "val2")
})
});
}
}
}
​
If you need read all points, you can use
var nodeList = Xmldocument.SelectNodes("level/info/ground/point");
SelectNodes return a list of nodes.
I would go for a slidely different way and use a data object. Then you don't have to analyse xml, you just code your data class:
[Serializable()]
public class CLevel
{
public string Info { get; set; }
}
[Serializable()]
public class CDatafile
{
public List<CLevel> LevelList { get; set; }
public CDatafile()
{
LevelList = new List<CLevel>();
}
}
public class DataManager
{
private string FileName = "Data.xml";
public CDatafile Datafile { get; set; }
public DataManager()
{
Datafile = new CDatafile();
}
// Load file
public void LoadFile()
{
if (System.IO.File.Exists(FileName))
{
System.IO.StreamReader srReader = System.IO.File.OpenText(FileName);
Type tType = Datafile.GetType();
System.Xml.Serialization.XmlSerializer xsSerializer = new System.Xml.Serialization.XmlSerializer(tType);
object oData = xsSerializer.Deserialize(srReader);
Datafile = (CDatafile)oData;
srReader.Close();
}
}
// Save file
public void SaveFile()
{
System.IO.StreamWriter swWriter = System.IO.File.CreateText(FileName);
Type tType = Datafile.GetType();
if (tType.IsSerializable)
{
System.Xml.Serialization.XmlSerializer xsSerializer = new System.Xml.Serialization.XmlSerializer(tType);
xsSerializer.Serialize(swWriter, Datafile);
swWriter.Close();
}
}
Then you can use it to create, save and load the file like this:
DataManager dataMng = new DataManager();
// Create some data
CLevel level = new CLevel();
level.Info = "Testlevel";
dataMng.Datafile.LevelList.Add(level);
// Save to file
dataMng.SaveFile();
// Load from file
dataMng.LoadFile();
So you can do everything in code checked by the compiler. Makes life a lot easier, or what do you think?

Find undeclared namespace'prefix

I'd like to retrieve each undeclared namespaces' prefix in a Xml file on load using (where msCurrentContent is a memorystream) :
xmlCurrentDoc = new XmlDocument();
xmlCurrentDoc.Load(msCurrentContent);
For example, when loading a Xml file with the following declaration :
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="mondoc" xls:schemaLocation="mondoc.xsd">
It must retrieve the undeclared prefix xls without throwing an exception (as it does know).
What is the best way to do this ?
Thanks for your help !
This is really hacky, but you could subclass XmlNamespaceManager and add fake namespaces as you encounter unknown prefixes:
public class MyXmlNamespaceManager : XmlNamespaceManager
{
const string DefaultMissingNamespacePrefix = "http://missing.namespace.prefix.net/2014/";
private string MissingNamespacePrefix { get; set; }
private int NextMissingNamespaceIndex { get; set; }
// The dictionary consists of a collection of namespace names keyed by prefix.
public Dictionary<string, List<string>> MissingNamespaces { get; private set; }
public MyXmlNamespaceManager(XmlNameTable nameTable)
: this(nameTable, null) { }
public MyXmlNamespaceManager(XmlNameTable nameTable, string missingNamespacePrefix)
: base(nameTable)
{
this.MissingNamespacePrefix = (string.IsNullOrEmpty(missingNamespacePrefix) ? DefaultMissingNamespacePrefix : missingNamespacePrefix);
this.MissingNamespaces = new Dictionary<string, List<string>>();
}
void AddMissingNamespace(string prefix)
{
if (string.IsNullOrEmpty(prefix))
return;
string uri;
do
{
int index = NextMissingNamespaceIndex++;
uri = MissingNamespacePrefix + index.ToString();
}
while (LookupPrefix(uri) != null); // Just in case.
Debug.WriteLine(string.Format("Missing namespace \"{0}\" found, added fake namespace \"{1}\"", prefix, uri));
AddNamespace(prefix, uri);
MissingNamespaces.Add(prefix, uri);
}
public override bool HasNamespace(string prefix)
{
var result = base.HasNamespace(prefix);
if (!result)
AddMissingNamespace(prefix);
result = base.HasNamespace(prefix);
return result;
}
public override string LookupNamespace(string prefix)
{
var result = base.LookupNamespace(prefix);
if (result == null)
AddMissingNamespace(prefix);
result = base.LookupNamespace(prefix);
return result;
}
}
public static class DictionaryExtensions
{
public static void Add<TKey, TValue>(this IDictionary<TKey, List<TValue>> listDictionary, TKey key, TValue value)
{
if (listDictionary == null)
throw new ArgumentNullException();
List<TValue> values;
if (!listDictionary.TryGetValue(key, out values))
{
listDictionary[key] = values = new List<TValue>();
}
values.Add(value);
}
}
And then, to test:
string xml = #"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""no""?>
<Document xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns=""mondoc"" xls:schemaLocation=""mondoc.xsd"">
</Document>
";
XmlDocument xmlDoc;
using (var stream = new StringReader(xml))
{
var settings = new XmlReaderSettings();
settings.NameTable = new NameTable();
var manager = new MyXmlNamespaceManager(settings.NameTable);
XmlParserContext context = new XmlParserContext(null, manager, null, XmlSpace.Default);
using (var xmlReader = XmlReader.Create(stream, settings, context))
{
xmlDoc = new XmlDocument();
xmlDoc.Load(xmlReader);
}
}
string newXml;
using (var writer = new StringWriter())
{
xmlDoc.Save(writer);
newXml = writer.ToString();
}
Debug.WriteLine(newXml);
Which produces the following result:
<?xml version="1.0" encoding="utf-16" standalone="no"?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="mondoc" xls:schemaLocation="mondoc.xsd" xmlns:xls="http://missing.namespace.prefix.net/2014/0">
</Document>
At least, it's not an exception. Note - only partially tested.

The specified node cannot be inserted as the valid child of this node, because the specified node is the wrong type

I am dynamically building the xml through C# code and I get this error
"The specified node cannot be inserted as the valid child of this
node, because the specified node is the wrong"
This is my main class
internal class Program
{
private static void Main(string[] args)
{
CreateXml xml = new CreateXml();
xml.multipleXML();
}
}
I have commented as “ERROR” below where i am getting run time exception. Please help how to fix this error.
My Xml Class is here.
internal class CreateXml
{
private XmlDocument HandlingXmlDoc;
private String baseHandlingXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?><SHandling><BLocation><SLocation><Identifier>02898</Identifier></SLocation></BLocation><Context><UserName>0289800001</UserName><Application>STOCK</Application></Context><Counting><SubmissionDateTime>2014-04-02T16:38:48.9345238+01:00</SubmissionDateTime><ProcessImmediately>YES</ProcessImmediately><Counts><Count><ProductIdentifier>050025488</ProductIdentifier><CountDateTime>2014-04-02T16:38:49.366567+01:00</CountDateTime><LocationCounts></LocationCounts></Count></Counts></Counting></SHandling>";
private XmlDocument locCountXmlDocument;
private String baseLocCountXML = "<LocationCount><Name>Bangalore</Name><SCounts><SCount><Quantity>1</Quantity><UnitOfMeasure>CASES</UnitOfMeasure></SCount><SCount><Quantity>1</Quantity><UnitOfMeasure>SINGLES</UnitOfMeasure></SCount></SCounts></LocationCount>";
public CreateXml()
{
Initialise();
}
public String GetStockHandlingXmlString { get { return HandlingXmlDoc.OuterXml; } }
public XmlDocument GetStockHandlingXmlDocument { get { return HandlingXmlDoc; } }
private void Initialise()
{
HandlingXmlDoc = new XmlDocument();
HandlingXmlDoc.LoadXml(baseHandlingXML);
locCountXmlDocument = new XmlDocument();
locCountXmlDocument.LoadXml(baseLocCountXML);
}
public void multipleXML()
{
XmlNode countNode = HandlingXmlDoc.CreateNode(XmlNodeType.Element, "Count", null);
XmlNode productIdentifierNode = HandlingXmlDoc.CreateNode(XmlNodeType.Element, "ProductIdentifier", null);
productIdentifierNode.InnerText = "123345";
XmlNode countDateTimeNode = HandlingXmlDoc.CreateNode(XmlNodeType.Element, "CountDateTime", null);
countDateTimeNode.InnerText = DateTime.Now.ToString();
//XmlNode locationCountNode = HandlingXmlDoc.CreateNode(XmlNodeType.Element, "LocationCounts", null);
countNode.AppendChild(productIdentifierNode);
countNode.AppendChild(countDateTimeNode);
countNode.AppendChild(SetNewLocation("Bangalore","30","30"));//ERROR
HandlingXmlDoc.SelectSingleNode("//SHandling//Counting//Counts").AppendChild(countNode);
}
private XmlNode SetNewLocation(String location, String casesQuantity, String singlesQuantity)
{
XmlDocument docCountXml = new XmlDocument();
docCountXml.LoadXml(baseLocCountXML);
SetValue(docCountXml, "LocationCount/Name", location);
var xmlNodeList = docCountXml.SelectNodes("LocationCount/SCounts/SCount/Quantity");
xmlNodeList[0].FirstChild.Value = casesQuantity;
xmlNodeList[1].FirstChild.Value = singlesQuantity;
return docCountXml.SelectSingleNode("/");
}
private static void SetValue(XmlDocument xmlDocument, String key, String value)
{
var xmlNode = xmlDocument.SelectSingleNode(key);
xmlNode.FirstChild.Value = value;
}
}
The problem is that you are inserting an external xmlnode from different xml.
my edit is here, I use a workaround to load the xmlnode in the new document and then append it to your node
countNode.AppendChild(countNode.OwnerDocument.ImportNode(test, true));
try this solution
public void multipleXML()
{
XmlNode countNode = HandlingXmlDoc.CreateNode(XmlNodeType.Element, "Count", null);
XmlNode productIdentifierNode = HandlingXmlDoc.CreateNode(XmlNodeType.Element, "ProductIdentifier", null);
productIdentifierNode.InnerText = "123345";
XmlNode countDateTimeNode = HandlingXmlDoc.CreateNode(XmlNodeType.Element, "CountDateTime", null);
countDateTimeNode.InnerText = DateTime.Now.ToString();
//XmlNode locationCountNode = HandlingXmlDoc.CreateNode(XmlNodeType.Element, "LocationCounts", null);
countNode.AppendChild(productIdentifierNode);
countNode.AppendChild(countDateTimeNode);
var test = SetNewLocation("Bangalore", "30", "30");
countNode.AppendChild(countNode.OwnerDocument.ImportNode(test, true));
//countNode.AppendChild(test);//ERROR
HandlingXmlDoc.SelectSingleNode("//SHandling//Counting//Counts").AppendChild(countNode);
}
and another edit in SetNewLocation function
(my edit return docCountXml.SelectSingleNode("LocationCount");)
private XmlNode SetNewLocation(String location, String casesQuantity, String singlesQuantity)
{
XmlDocument docCountXml = new XmlDocument();
docCountXml.LoadXml(baseLocCountXML);
SetValue(docCountXml, "LocationCount/Name", location);
var xmlNodeList = docCountXml.SelectNodes("LocationCount/SCounts/SCount/Quantity");
xmlNodeList[0].FirstChild.Value = casesQuantity;
xmlNodeList[1].FirstChild.Value = singlesQuantity;
return docCountXml.SelectSingleNode("LocationCount");
}
for references here and here

How to append node to xml file in Silverlight?

I have a xml file in ClientBin folder with the name XMLFile1.xml.
There are three nodes in file:
<?xml version="1.0" encoding="utf-8" ?>
<People>
<Person FirstName="Ram" LastName="Sita"/>
<Person FirstName="Krishna" LastName="Radha"/>
<Person FirstName="Heer" LastName="Ranjha"/>
</People>
I can read nodes from file like that:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Uri filePath = new Uri("XMLFile1.xml", UriKind.Relative);
WebClient client1 = new WebClient();
client1.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client1_DownloadStringCompleted);
client1.DownloadStringAsync(filePath);
}
void client1_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
XDocument doc = XDocument.Parse(e.Result);
IEnumerable<Person> list = from p in doc.Descendants("Person")
select new Person
{
FirstName = (string)p.Attribute("FirstName"),
LastName = (string)p.Attribute("LastName")
};
DataGrid1.ItemsSource = list;
}
}
But i cant append node to this. What i have done yet with XDocument and XMLDocument gave me compile errors. Thanks.
Update : For example I have tried something like that:
string FirstName = "Ferhad";
string LastName = "Cebiyev";
XDocument xmlDoc = new XDocument();
string path = "C:\\Users\\User\Desktop\\temp\\SilverlightApplication3\\SilverlightApplication3.Web\\ClientBin\\XMLFile1.xml";
xmlDoc.Load(path);
xmlDoc.Add(new Person { FirstName=FirstName, LastName = LastName});
xmlDoc.Save(path);
This is the problem:
xmlDoc.Add(new Person { FirstName=FirstName, LastName = LastName});
Two issues:
That tries to add to the root of the document. There's already a root element, so that will fail.
That's trying to add a Personto the document. You want to add an XElement.
So you probably want:
xmlDoc.Root.Add(new XElement("Person",
new XAttribute("FirstName", FirstName),
new XAttribute("LastName", LastName)));

Categories

Resources