Can not save string / node to XML WP8 - c#

I am reading the contents of an xml file perfectly into a longlistselector with tap events attached. All working great. The file sits in the main assets folder of the project.
Now i would also like to add strings/ nodes to my simple XML, but for some reason i can't find the right syntax to save it to the file.
My xml file looks like:
<?xml version="1.0" encoding="utf-8" ?>
<phrases>
<item><name>What is your name?</name></item>
<item><name>How old are you?</name></item>
</phrases>
Now I tried the following inside of a click event of a button:
XDocument xDoc = XDocument.Load("phrases.xml");
var contactsElement = new XElement("item",
new XElement("name", "blalllllaaaallaala")));
xDoc.Add(contactsElement);
xDoc.Save("phrases.xml");
VS2013 tells me that the xDoc.Save("phrases.xml") has invalid arguments. When i read from that file i provide the same path, so i dont understand what is expected here? Please give some suggestions.

Just try out with this snippet...
// load original XML from the stream
XDocument loadedData = XDocument.Load(stream);
// create a new parent XML structure (new root) and load the original nodes
var newXml = new XDocument(new XElement("Histories"));
newXml.Root.Add(loadedData.Root);
// create the new node
var contactsElement = new XElement("item",
new XElement("name", "blalllllaaaallaala")));
NewNode.Add(contactsElement);
// add the new node
newXml.Root.Add(NewNode);
// save the stream
newXml.Save(stream);
For more have a look here too.

Related

Update an xml file in a storage folder by adding nodes using C#

I'm making a universal app in C# and I'm trying to update an xml file in the storage folder by adding some nodes to it. Ideally, starting with a file like this
<?xml version="1.0" encoding="UTF-8"?>
<MyRoot>
<ParentNode>
<myNode1>value1</myNode1>
<myNode2>value2</myNode2>
</ParentNode>
</MyRoot>
I would like to add other nodes in order to obtain
<?xml version="1.0" encoding="UTF-8"?>
<MyRoot>
<ParentNode>
<myNode1>value1</myNode1>
<myNode2>value2</myNode2>
</ParentNode>
<ParentNode>
<myNode1>value3</myNode1>
<myNode2>value4</myNode2>
</ParentNode>
</MyRoot>
What I obtain instead is an invalid xml file with the content I want appended to the previous content like this
<?xml version="1.0" encoding="UTF-8"?>
<MyRoot>
<ParentNode>
<myNode1>value1</myNode1>
<myNode2>value2</myNode2>
</ParentNode>
</MyRoot><?xml version="1.0" encoding="utf-8"?>
<MyRoot>
<ParentNode>
<myNode1>value1</myNode1>
<myNode2>value2</myNode2>
</ParentNode>
<ParentNode>
<myNode1>value3</myNode1>
<myNode2>value4</myNode2>
</ParentNode>
</MyRoot>
Here is the code
StorageFile myFile = await ApplicationData.Current.LocalFolder.GetFileAsync("myFile.xml");
using (IRandomAccessStream writeStream = await myFile.OpenAsync(FileAccessMode.ReadWrite))
{
// convert IRandomAccessStream to IO.Stream
Stream s = writeStream.AsStreamForWrite();
//xml
XDocument document = XDocument.Load(s);
document.Root.Add(
new XElement("ParentNode",
new XElement("myNode1", "value3"),
new XElement("myNode2", "value4"))
);
document.Save(s);
}
After your call to XDocument.Load you are positioned at the end of the stream, so the call to document.Save will append the new contents at the end of the stream.
As long as you're only adding nodes to the existing XML making the file longer with every save, you could resolve the issue by moving to the beginning of the stream, before calling document.Save:
document.Root.Add(
new XElement("ParentNode",
new XElement("myNode1", "value3"),
new XElement("myNode2", "value4"))
);
s.Seek(0, SeekOrigin.Begin); // <-- add this line
document.Save(s);
If you start removing nodes, this won't work because not all of the old file will be overwritten and some remains will stay at the end. In this case you will need to close the stream after loading it and create a new file for saving by overwriting the existing one:
StorageFile newFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("myFile.xml",
CreationCollisionOption.ReplaceExisting);
Try something along the lines of:
XmlDocument doc = new XmlDocument();
doc.Load("yourfile.xml");
var root = doc.DocumentElement;
var parentNode = doc.CreateElement("ParentNode");
root.AppendChild(parentNode);
var myNode1 = doc.CreateElement("myNode1");
myNode1.Value = "value3";
parentNode.AppendChild(myNode1);
// ...add more nodes etc...
doc.Save("yourfile.xml");

exception occurs while saving XML using c#

I am trying to update an existing XML file by adding a new child node using c#.
Everything is OK if I save it by new name but I want to update the same file and while doing it, got the following exception:
System.IO.IOException:Process cannot access the file... because it is
being used by another process
Here is my code: (I am trying to add a new default node)
XmlDocument doc = new XmlDocument();
string path = #"C:\Debug\default.xml";
doc.Load(path);
XmlNode NName = doc.CreateElement("default");
XmlNode SNO = doc.CreateElement("SNo");
SNO.InnerText = "2";
NName.AppendChild(SNO);
doc.DocumentElement.AppendChild(NName);
doc.Save(path);
Also XML file:
<?xml version="1.0" standalone="yes"?>
<NewDataSet>
<default>
<SNo>1</SNo>
</default>
</NewDataSet>
If you are sure the file is only being used by your process, then simply read it into a byte array, close the file, then save it again:
(I am using .net 4.0 for this sample):
XmlDocument doc = new XmlDocument();
byte[] content = File.ReadAllBytes(path);
using (var memStream = new MemoryStream(content))
{
doc.Load(memStream);
}
XmlNode NName = doc.CreateElement("default");
XmlNode SNO = doc.CreateElement("SNo");
SNO.InnerText = "2";
NName.AppendChild(SNO);
doc.DocumentElement.AppendChild(NName);
doc.Save(path);

XDocument won't save to file

Trying to write some simple code and see if I can get a hang of this XML business.
public static void Save() {
XDocument doc = XDocument.Load("Repository/Test.xml");
foreach (Produs p in produse) {
// Yes there are multiple elements ('p'), have checked
XElement root = new XElement("Produs");
root.Add(new XElement("Name", p.getName()));
root.Add(new XElement("Quantity", p.getQuant().ToString()));
doc.Element("Produse").Add(root); // This "Produse" here should be the root element of the XML file, right ?
//doc.Save("Repository/Test.xml");
}
doc.Save("Repository/Test.xml"); // moved here
}
No compile, or run time error, but nothing gets changed within the file. I do read from the file, so it does work.
Extra info on the .xml file (within visual studio):
Build action: Content
Copy to output directory: Copy always

Adding data to an existing xml file

I am using the follwing syntax to add data to already existing xml file in the following way:
XmlTextReader Reader = new XmlTextReader("ServerPaths.xml");
DataSet dsNewList = new DataSet();
dsNewList.ReadXml(Reader);
Reader.Close();
DataTable dt = dsNewList.Tables[0];
dt.Rows.Add(txtNewServerPath.Text);
dt.WriteXml("ServerPaths.xml",false);
But, i was getting error at last line as:
System.IO.IOException was unhandled
Message=The process cannot access the file 'C:\Documents and Settings\590000\my documents\visual studio 2010\Projects\EasyDeployer\EasyDeployer\bin\Debug\ServerPaths.xml' because it is being used by another process
Please help in solving this error. or is there any other way to do this?
My xml file looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<ServerList>
<ServerPath>C:\\Avinash\\Dev1</ServerPath>
<ServerPath>C:\\Avinash\\Dev1</ServerPath>
</ServerList>
I just wanted to add new serverpath..
You could also try adding XmlNode's to the xml document like this:
XmlDocument xd = new XmlDocument();
xd.Load("ServerPaths.xml");
XmlNode rootNode = xd.DocumentElement;
XmlNode serverPathNode = xd.CreateElement("ServerPath");
serverPathNode.InnerText = txtNewServerPath.Text; // Your value
rootNode.AppendChild(serverPathNode);
xd.Save("ServerPaths.xml");

Xml root node not closed

I'm using xmlwriter to create an xml document. The xml document looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<ExceptionsList />
How can i prevent the /> and appropriately end the root node?
Because of this, i can't append anything to the root node.
My code for creating the xml file looks like this:
string formatDate = DateTime.Now.ToString("d-MMM-yyyy");
XmlTextWriter xmlWriter = new XmlTextWriter(xmlfileName, Encoding.UTF8);
xmlWriter.Formatting = Formatting.Indented;
xmlWriter.Indentation = 3;
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("ExceptionsList"); // ExceptionsList (Root) Element
xmlWriter.WriteEndElement(); // End of ExceptionsList (Root) Element
xmlWriter.WriteEndDocument();
xmlWriter.Flush();
xmlWriter.Close();
And I append to the root node like this:
XDocument xml = XDocument.Load(xmlFileName);
XElement root = xml.Root;
root.Add(new XElement("Exception",
new XElement("Exception Type", exceptionType),
new XElement("Exception Message", exceptionMessage),
new XElement("InnerException", innerException),
new XElement("Comment", comment)));
xml.Save(xmlFileName);
This gives me a stackoverflow at runtime error too.
Any help would be appreciated.
Thanks in advance!
Your code is right, and you don't need to change how your ExceptionsList element is closed.
xmlWriter.WriteStartElement("ExceptionsList"); // ExceptionsList (Root) Element
xmlWriter.WriteStartElement("Exception"); // An Exception element
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement(); // End of ExceptionsList (Root) Element
In your second snippet, you need to remove those white spaces from element name, as XML specification forbid that and add your elements into your XDocument instance, like this:
XDocument xml = new XDocument();
xml.Add(new XElement("Exception",
new XElement("ExceptionType", "Exception"),
new XElement("ExceptionMessage",
new XElement("InnerException", "innerException")),
new XComment("some comment")));
xml.Save("sample2.xml");
I believe the problem is here:
new XElement("Exception Type", exceptionType),
new XElement("Exception Message", exceptionMessage),
Neither Exception Type nor Exception Mesage is a valid name for an xml element. Then of course, if you use this (doomed) method to log the error... stack overflow.

Categories