How can I delete an object from an XML file - c#

I have a problem. I have an XML file and there I save projects. I try, for example to delete the project2 but I have not found anything that works. Is there a good way to solve it easily and cleanly?
c# Code:
private void WriteToXML(XmlSerializer xs, ObservableCollection<ProjektListItem> projekte)
{
using (StreamWriter wr = new StreamWriter(#".\LastUsedProjects.xml"))
{
projekte.Remove(SelectedItem);
xs.Serialize(wr, projekte);
}
}
XML file:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfProjektListItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ProjektListItem>
<_Name>Projekt1</_Name>
<_Path>C:\Users\Bob\Desktop\Projekt1.xml</_Path>
<_Date>12.07.2019 10:46</_Date>
<_Source />
</ProjektListItem>
<ProjektListItem>
<_Name>Projekt2</_Name>
<_Path>C:\Users\Bob\Desktop\Projekt1.xml</_Path>
<_Date>12.07.2019 10:46</_Date>
<_Source />
</ProjektListItem>
</ArrayOfProjektListItem>
SelectedItem comes from a ComboBox in which i select my project. I know how to remove it from the Collection but i dont know how to update the xml. The XML file is the Illustration from my collection. I remove the selectedItem from the Collection and now i have to remove it from the xml file respectively update / override it in the XML File.

Related

Saving an xml file using stream results in a duplicate root elements

So I'm attempting to open an xml file, add an XElement to the root element, and save it. Except my C# Code:
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync("UserPinouts.tpack", CreationCollisionOption.OpenIfExists);
using (var stream = await file.OpenStreamForWriteAsync())
{
XDocument doc = XDocument.Load(stream);
doc.Root.Add(new XElement(XElement.Parse(CurrentPinOut)));
doc.Save(stream);
Debug.WriteLine(doc.ToString());
stream.Flush();
}
Gives me the following xml file:
<?xml version="1.0" encoding="utf-8" ?>
<RootElement>
<XElement1/>
</RootElement>
<?xml version="1.0" encoding="utf-8" ?>
<RootElement>
<XElement1/>
<XElement2/>
</RootElement>
Instead of just that second part. I've tried changing the way I add the XElement, but I get this everytime, so I'm guessing it must be a problem with the way I open/close the stream. How could I fix this?
Try to reset stream position to the beginning, just before calling Save() method :
stream.Position = 0;
doc.Save(stream);
I have seen this solved similar problem in old Windows Phone questions. These are some of them : 1. Appending new XElement adds an entire XML to existing xml in stream, 2. updating an existing xml file in Windows Phone

export list of object to xml file in c#

I try to export a list of object(type of "Doctor") to an xml file in c#.
It compiles and runs, but the file I get isn't correct. Can someone please can tell me what I did incorrect?
the code is:
public static void exportAsXml(string fileName, List<Entity> ListOfEntity)
{
FileInfo file = new FileInfo(fileName + ".xml");
StreamWriter sw = file.AppendText();
System.Xml.Serialization.XmlSerializer writer = new System.Xml.Serialization.XmlSerializer(typeof(Doctor));
foreach (Entity e in ListOfEntity)
{
writer.Serialize(sw,e as Doctor);
}
sw.Close();
}
the xml file is:
<?xml version="1.0" encoding="utf-8"?>
<Doctor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>87587579</ID>
<FirstName>Dan</FirstName>
<LastName>Adi</LastName>
<Gender>male</Gender>
<Salary>15000</Salary>
</Doctor><?xml version="1.0" encoding="utf-8"?>
<Doctor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>302342246</ID>
<FirstName>Lital</FirstName>
<LastName>Gal</LastName>
<Gender>female</Gender>
<Salary>25600</Salary>
</Doctor><?xml version="1.0" encoding="utf-8"?>
<Doctor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>205992457</ID>
<FirstName>Yaron</FirstName>
<LastName>Mor</LastName>
<Gender>male</Gender>
<Salary>10000</Salary>
</Doctor>
Thanks!
First of all, the resulting xml violates 2 core rules.
Xml file should have only one <?xml version="1.0" encoding="utf-8"> declaration
All your xml should be enclosed inside one root file.
In other words, in loop you generate a separate, fully-fledged xml file for each item.
Try this
var writer = new System.Xml.Serialization.XmlSerializer(typeof(List<Doctor>));
writer.Serialize(sw, ListOfEntity);
You are corrupting the xml file by serializing the doctor objects and saving it to the same file using file.AppendText();, generating corrupted xml with multiple <?xml version="1.0" encoding="utf-8"?> declarations as consequence.
You should serialize the List<Doctor> instead of serializing each doctor alone and modifying the xml file by appending text.
If you want to modify a serialized object saved inside a file, you need to deserialize the file into an object, modify it and then replace the file with the new serialized object. you cannot simply append it.

Incorrect structured XML document after deleting element

When I try to load a XML file after deleting an Element from the file, it shows the following error: Unexpected XML declaration. The XML declaration must be the first node in the document, and no white space characters are allowed to appear before it. Line 9, position 10. What is wrong with my code?
This is my XML file:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<booze>booze1</booze>
<booze>booze2</booze>
<booze>booze3</booze>
<booze>booze4</booze>
</data>
And my code:
using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream("favorites.xml", FileMode.Open, file))
{
XDocument xDoc = XDocument.Load(stream, LoadOptions.None);
// delete node
xDoc.Descendants("data").Elements("booze").Where(x => x.Value == favorite).DescendantsAndSelf().Remove();
xDoc.Save(stream);
}
}
My guess is that when you run the code for the first time, the delete succeeds and your XDoc contains :
<?xml version="1.0" encoding="utf-8"?>
<data>
<booze>booze1</booze>
<booze>booze2</booze>
<booze>booze4</booze>
</data>
, but when calling XDoc.Save you simply append this to the favorites.xml file. After that, the favorites.xml file contains something like this:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<booze>booze1</booze>
<booze>booze2</booze>
<booze>booze3</booze>
<booze>booze4</booze>
</data><?xml version="1.0" encoding="utf-8"?>
<data>
<booze>booze1</booze>
<booze>booze2</booze>
<booze>booze4</booze>
</data>
That is why all the subsequent file loads throw the error. What you should do is overwrite the file, and not append to it. The first way of doing that that comes to mind is to close the stream, open it with Mode.Truncate and then save the XDoc. Or you can delete and recreate the file. I am not that familiar with IsolatedStorageFiles so this is a wild guess.

"Cannot Serialize Multidimensional Arrays" -What is it, and what did I type wrong?

I've been trying to Import XML files into my XNA project for quite a while.
Just when I thought that I'd gotten it all done, this error pops up. Lots of searching, and I haven't found an answer that helps.
This is a clipped version of my XML document:
<?xml version="1.0" encoding="utf-8" ?>
<XnaContent>
<!-- TODO: replace this Asset with your own XML asset data. -->
<Asset Type="Library.Room">
<Tile itIs="Wall">
<x>0</x>
<y>0</y>
<o>0</o>
</Tile>
</Asset>
</XnaContent>
When trying to Build, I get this Error:
"Building content threw RankException: Cannot serialize multidimensional arrays."
Even commenting out lines of my project code do nothing to change this error, so I know that it's something in how I've written my XML. ( Which I thought was okay )
So, that tells me that I'm probably writing my XML wrong. What is a MultiDimensional Array in XML, and how can I avoid it?
___Added Info
I add the XML info to an Array here, piece by piece. --naturally, I thought that this was the problem at first, but commenting any of this out has no effect.
public void loadFromFile(string fileName, Room r)
{
var doc = XElement.Load(fileName);
foreach (var v in roomDoc.Elements("Tile"))
{
r.blueprint.SetValue(new Things.Wall((int)v.Element("o")), (int)v.Element("x"), (int)v.Element("y"));
}
}

How to edit XML file shown in a ListView in C#?

I am working on a C# application for a scanning device and I came across a problem. I get my configuration settings from an xml file, that I get from a server every time the application is run. However, if the configuration is wrong, I can't request a new configuration because the Server Url is in the xml. So I decided I want to have editing functionality. Here's how I show the config:
private void list()
{
if (this.listViewConf.Items.Count != 0)
this.listViewConf.Items.Clear();
this.addItem("Operator", Data.cuser);
this.addItem("Warehouse", Data.cware);
this.addItem("Server URI", Config.uri(Config.socket));
this.addItem("Timeout", Config.get(Config.socket, Config.atime));
this.addItem("Config file", Config.path("config.xml"));
this.addItem("Data backup", Config.path("data.xml"));
this.listViewConf.Visible = true;
}
private void addItem(String name, String value) {
ListViewItem item = new ListViewItem();
item.Text = name;
item.SubItems.Add(value);
this.listViewConf.Items.Add(item);
}
Where listViewConf is a ListView. My questins are - how to know which row of the ListView is selected (given that I have a button Edit) and more importantly, how to edit the xml file? The ListView consists of Name | Value pairs and here's a sample config.xml:
<?xml version="1.0" encoding="utf-8" ?>
<wms>
<setup>
<config path="/Flash File Store/WMS/" file="config.xml" />
<socket path="http://ware.aip/interface/ck/" file="socket.php" timeout="10000" />
</setup>
<users>
<user id="1" code="01" name="User" ware="1" />
</users>
<warehouses>
<ware id="1" code="T" name="Test" />
</warehouses>
<tasktypes>
<type id="1" code="T" name="Test" />
</tasktypes>
</wms>
And also - I know its possible to create an editable ListView, but if there is a simpler solution (like with an edit button), I'd be happy to use it.
Thanks in advace.
Create a serializable class from the XML using xsd.exe. Use this class to deserialize the data in the XMl into a graph of POCO objects, which in turn you can bind to the ListView. You can directly edit the objects now, rather than trying to estimate where in the XML nodes you should edit.
Once all editing is done, serialize the objects back into XML.

Categories