I'm new to C# and currently trying to create a simple login screen using windows forms. The program takes the forms input and saves the username and password to an XML file. I'm just wondering how I can save more than one user instead of the previous users data being overwritten when I save a new user. This is the code I'm currently using.
{
XmlTextWriter write = new XmlTextWriter("XML.xml", Encoding.UTF8);
write.WriteStartElement("USER");
write.WriteStartElement("username");
write.WriteString(textBox1.Text);
write.WriteEndElement();
write.WriteStartElement("passsword");
write.WriteString(textBox2.Text);
write.WriteEndElement();
write.WriteEndElement();
write.Close();
}
Try this:
XmlDocument xmlDoc = new XmlDocument();
string filePath = Path.Combine(#"C:\assets\" + "users.xml");
XmlNode usersNode;
if (File.Exists(filePath))
{
xmlDoc.Load(filePath);
usersNode = xmlDoc.SelectSingleNode(#"Users");
}
else
{
usersNode = xmlDoc.CreateElement("Users");
xmlDoc.AppendChild(usersNode);
}
XmlElement user = xmlDoc.CreateElement("User");
XmlElement userName = xmlDoc.CreateElement("UserName");
XmlElement pass = xmlDoc.CreateElement("Pass");
userName.InnerText = "TestUser";
pass.InnerText = "TemPass";
user.AppendChild(userName);
user.AppendChild(pass);
usersNode.AppendChild(user);
xmlDoc.Save(filePath);
Related
I am trying to figure out how to read and write files in a UWA application. I understand that I need to open a FileStreamm, but I can't figure out how to do that.
I started with this code:
FileStream fs = new FileStream(#"C:\XML\test.txt", FileMode.Create, FileAccess.Write);
seems to work, no red lines.
At the end of all of that I am told to put in Flush and Close, like this:
FileStream fs = new FileStream(#"C:\XML\test.txt", FileMode.Create,
...
fs.Flush();
fs.Close();
Now, this is where I hit a snag, because fs.Close(); is not even on the list of functions on fs. I just get a red line in my IDE if I try to hardcode it.
Can someone please take the time to help me understand how to do this with UWA? For some reason it seems like there is a different approach in Windows 10 apps, and I have a VERY hard time finding anything that shows me how to do it right. All the tutorials and SOF forum input are about older versions (non-UWA).
When I do this in a console application it all works as expected.
My end goal is to be able to read and write to an XML file in this kind of fashion:
XDocument doc = XDocument.Load(input);
XElement person = doc.Element("Person");
person.Add(new XElement("Employee",
new XElement("Name", "David"),
new XElement("Dept", "Chef")));
doc.Save(output);
I'm going down this path because an answer to my previous question told me to use a FileStream, but I simply cannot make that work in UWA.
You cannot just access any file from a Universal Windows App. Access to the file system is restricted.
See the documentation for details.
To help you further we need to know more about your application. What kind of files do you want to access for what reason?
Example on how to read an Xml File, modify it and store it in an Universal app. You need a button with the following Click handler and a TextBox named "TextBoxLog".
private async void ButtonDemo_Click(object sender, RoutedEventArgs e)
{
// Get our local storage folder
var localFolder = ApplicationData.Current.LocalFolder;
XmlDocument xmlDocument;
// Try to get file
var file = await localFolder.TryGetItemAsync("MyData.xml") as IStorageFile;
if(file != null)
{
// File exists -> Load into XML document
xmlDocument = await XmlDocument.LoadFromFileAsync(file);
}
else
{
// File does not exist, create new document in memory
xmlDocument = new XmlDocument();
xmlDocument.LoadXml(#"<?xml version=""1.0"" encoding=""UTF-8""?>" + Environment.NewLine + "<root></root>");
}
// Now show the current contents
TextBoxLog.Text = "";
var lEntries = xmlDocument.GetElementsByTagName("Entry");
foreach(var lEntry in lEntries)
{
TextBoxLog.Text += lEntry.InnerText + Environment.NewLine;
}
// Now add a new entry
var node = xmlDocument.CreateElement("Entry");
node.InnerText = DateTime.Now.ToString();
xmlDocument.DocumentElement.AppendChild(node);
// If the file does not exist yet, create it
if(file == null)
{
file = await localFolder.CreateFileAsync("MyData.xml");
}
// Now save the document
await xmlDocument.SaveToFileAsync(file);
}
Okay, the (simple) solution is to put the xml-file in the PROJECTFOLDER/bin/x86/debug/appX and then write the data to a list this way:
public class dataRaw
{
public string data { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
}
//You can call this class with x = collectionGenerator.getList() (it returns a list<T>)
public class collectionGenerator
{
public static List<dataRaw> getList()
{
//This is the xml file in the folder
var doc = XDocument.Load("Data.xml");
//This parse the XML and adds in to the list "dataList"
var dataList = doc.Root
.Descendants("Person")
.Select(node => new dataRaw
{
//data, firstName and lastName are in app variables from dataRaw put into listData.
//Number, FirstName and LastName are the nodes in the XML file.
data = node.Element("Number").Value,
firstName = node.Element("FirstName").Value,
lastName = node.Element("LastName").Value,
})
.ToList();
return dataList;
}
}
I have a simple XML file structured like this
<?xml version="1.0" encoding="utf-8" ?>
<event>
<name>Test Event</name>
<date>06/09/1990</date>
<description>Birthday</description>
<blogURL></blogURL>
</event>
What I am trying to achieve is to have a form accept user input to create a new XML document with the same structure that will overwrite the old one.
The XML document is in the same directory as the ASPX page that will accept the input.
When the user navigates to the PressRelease.aspx page, it loads the values in the document.
var doc = XDocument.Load(Server.MapPath("~/PressSection.xml"));
string currentEventName = (string)doc.Descendants("name").Single();
string currentEventDate = (string)doc.Descendants("date").Single();
string currentEventDescription = (string)doc.Descendants("description").Single();
string currentEventLink = (string)doc.Descendants("blogURL").Single();
if (currentEventLink.ToString() == "")
{
CurrentEventURL.Text = "This event has no URL";
}
CurrentEventName.Text = currentEventName;
CurrentEventDescription.Text = currentEventDescription;
CurrentEventDate.Text = currentEventDate;
This works. I am grabbing the user input and doing simple validation like this
string newEventName = NewEventName.Text;
string newEventDescription = NewDescription.Text;
string newEventDate = NewDate.SelectedDate.Value.Date.ToString();
string newEventURL = NewURL.Text;
if (newEventName == "")
{
MessageBox.Text = "Please enter a valid event name";
MessageBox.CssClass = "event_error";
return;
}
if (newEventDescription == "")
{
MessageBox.Text = "Please enter a valid description";
MessageBox.CssClass = "event_error";
return;
}
if (newEventDate == null)
{
MessageBox.Text = "Please select a valid date";
MessageBox.CssClass = "event_error";
return;
}
And finally, I build and save the new XML document like this
//Create new document
XDocument newEventDocument = new XDocument(new XDeclaration("1.0", "utf-8", null));
//Addd root node
XElement RootNode = new XElement("Event");
//add root node to new document
newEventDocument.Add(RootNode);
//Add event name element then add it to the new document
XElement eName;
eName = new XElement("name");
eName.Value = newEventName;
newEventDocument.Root.Add(eName);
//Add event date element then add it to the new document
XElement eDate;
eDate = new XElement("date");
eDate.Value = newEventDate;
newEventDocument.Root.Add(eDate);
//Add event description element then add it to the new document
XElement eDescription;
eDescription = new XElement("description");
eDescription.Value = newEventDescription;
newEventDocument.Root.Add(eDescription);
//Add event URL element then add it to the new document
XElement eURL;
eURL = new XElement("blogURL");
eURL.Value = newEventURL;
newEventDocument.Root.Add(eURL);
//Finally, save the document
newEventDocument.Save("PressSection.xml", SaveOptions.None);
The issue that my program throws is an invalid permissions problem.
Access to the path 'C:\Program Files (x86)\IIS Express\PressSection.xml' is denied.
My question is, how do I save this in the root of my project directory, instead of IN MY IIS Express folder? I need it to overwrite the existing 'PressSection.xml' file that already exists in my project. Thanks!
This worked for it. Sorry for such an easy question
string path = Server.MapPath("PressSection.xml");
newEventDocument.Save(Path.Combine(path));
Hope you can help me a bit. I'm trying to write to an XML file, but am struggling to write the method which, well, writes to the XML file. This is the XML file manually written (using Notepad++ etc.):
<software>
<software_entry
name="Adobe Acrobat X Standard"
path="Applications\Acrobat\Acrobat X Standard\AcroStan.msi"
type="msi"
switches="/qn ALLUSERS=1"
/>
<software_entry
name="Adobe Acrobat X Professional"
path="Applications\Acrobat\Acrobat X Pro\AcroPro.msi"
type="msi"
switches="/qn ALLUSERS=1"
/>
</software>
The aim of this part of the application is to write that using a GUI.
In the application, the user chooses the name of the XML file. It is then saved in the temp folder until further in the process when the user is asked where they would like to save it. Upon entering the desired name of the file and clicking Create, the method called "createAndLoadXML" is run. As its name would suggest, it creates and then loads an XML file (to populate a listview control on the form). Code can be seen below.
private void createAndLoadXML()
{
// Method to create XML file based on name entered by user
string tempPath = Path.GetTempPath();
string configFileName = fileNameTextBox.Text;
string configPath = tempPath + configFileName + ".xml";
// Create XDocument
XDocument document = new XDocument(
new XDeclaration("1.0", "utf8", "yes"),
new XComment("This XML file defines the software selections for use with the Software Installer"),
new XComment("XML file generated by Software Installer"),
new XElement("software",
new XElement("software_entry",
new XAttribute("name", ""),
new XAttribute("path", ""),
new XAttribute("type", ""),
new XAttribute("switches", ""))
)
);
document.Save(configPath);
configCreateLabel.Visible = true;
document = XDocument.Load(configPath);
}
Now, further down this form are 4 text boxes for user input, each relating to the attributes created (name, path, type and switches) The idea is the user will write in these text boxes, click an 'Add' button and then the program will write those 4 fields as attributes to this XML file. So far, I have this code, which is horribly incomplete and doesn't even use LINQ to XML.
private void writeToXML()
{
// Method to write lines to XML file based on user input
// Sets string variables
string fileName = softwareNameTextBox.Text;
string filePath = filePathTextBox.Text;
string fileType = installerType.Text.ToString();
string installSwitches = installSwitchesTextBox.Text;
using (XmlWriter xw = XmlWriter.Load(configPath)) //This line is wrong, I know
{
xw.WriteStartElement("software");
xw.WriteElementString("name", fileName);
xw.WriteElementString("path", filePath);
xw.WriteElementString("type", fileType);
xw.WriteElementString("switches", installSwitches);
xw.WriteEndElement();
}
}
Basically, could anyone please help me with the above method which writes to the XML the data the user has entered into the text box controls? I'm not sure how to load the previously created XML document (from my createAndLoadXML method), and how to write within the root element (software) using LINQ to XML.
Try this out. I think this should get you what you want assuming the XML exists beforehand since you are calling createAndLoadXML before this method. I wrote this in NotePad++, so I may have a error or two.
private void writeToXML()
{
// Method to write lines to XML file based on user input
// Sets string variables
string fileName = softwareNameTextBox.Text;
string filePath = filePathTextBox.Text;
string fileType = installerType.Text.ToString();
string installSwitches = installSwitchesTextBox.Text;
string FILE_PATH = "bla.xml";
XDocument xDoc = XDocument.Load(FILE_PATH);
xDoc.Root.Add(new XElement("software_entry",
new XAttribute("name", fileName),
new XAttribute("path", filePath),
new XAttribute("type", fileType),
new XAttribute("switches", installSwitches)
));
xDoc.Save(FILE_PATH);
}
Recently, I began developing an application that utilizes the use of XML documents in a C# program. Everything worked fine to begin with, but as I edited the code, and added a bit more features to the program in case the XML gets deleted, corrupted, etc, the program didn't want to function properly anymore.
The following code is used when submitting the data and transferring it to XML:
private void doneCreate_Click(object sender, EventArgs e)
{
//Initialize new XMLDocument class.
XmlDocument XmlDoc = new XmlDocument();
//See if the card data file is there, if not, create it.
if (File.Exists(xmlPath) == false)
{
using (FileStream createFile = File.Create(xmlPath))
{
Byte[] FileData = new UTF8Encoding(true).GetBytes(toBase64("<studycards></studycards>"));
// Add some information to the file.
createFile.Write(FileData, 0, FileData.Length);
createFile.Close();
}
XMLData = "<studycards></studycards>";
}
else
{
XMLData = readXML();
if (XMLData == "")
{
XMLData = "<studycards></studycards>";
}
else
{
XMLData = fromBase64(XMLData);
}
}
XmlDoc.LoadXml(XMLData);
XmlElement Group = XmlDoc.CreateElement("Group", null);
XmlAttribute Group_Attr = XmlDoc.CreateAttribute("Name");
Group_Attr.Value = groupName.Text;
Group.Attributes.Append(Group_Attr);
foreach (string[] Card in CardData)
{
try
{
FrontData = Card[0].ToString();
BackData = Card[1].ToString();
NewCard = XmlDoc.CreateElement("Card");
FrontElement = XmlDoc.CreateElement("Front");
FrontElement.InnerText = FrontData;
BackElement = XmlDoc.CreateElement("Back");
BackElement.InnerText = BackData;
NewCard.AppendChild(FrontElement);
NewCard.AppendChild(BackElement);
Group.AppendChild(NewCard);
}
catch
{
break;
}
}
XmlDoc.DocumentElement.AppendChild(Group);
XmlTextWriter write = new XmlTextWriter(xmlPath, null);
write.Formatting = Formatting.Indented;
XmlDoc.Save(write);
}
Upon attempting to click "Done" in the application, I'm presented with the following Exception:
The process cannot access the file 'C:\Users\Toshiba\documents\visual studio 2010\Projects\StudyCards\StudyCards\bin\Debug\Resources\card_data.xml' because it is being used by another process.
Any solutions?
This may well be at least part of the problem:
XmlTextWriter write = new XmlTextWriter(xmlPath, null);
write.Formatting = Formatting.Indented;
XmlDoc.Save(write);
You're never closing the writer, so I would expect it to keep the file open. That will stop future attempts to open the file, until the finalizer kicks in.
Alternatively it could be part of readXML(), which you haven't shown - again, if that leaves the file open, that would cause problems.
I have a problem with writing to xml file, placed in my application folder( windows 8, metro style). I’m getting Unauthorized AccessException when I’m trying to open file in read/write mode. I’ve done a lot of research, but still nothing. I tried this solution:
var sf = await Package.Current.InstalledLocation.GetFileAsync(#"data.xml");
XmlDocument xmlDoc;
using (var stream = await sf.OpenAsync(FileAccessMode.ReadWrite))
{
xmlDoc = await XmlDocument.LoadFromFileAsync(sf);
XmlElement root = xmlDoc.DocumentElement;
XmlElement xe = xmlDoc.CreateElement("debt");
XmlElement id = xmlDoc.CreateElement("Id");
id.InnerText = Guid.NewGuid().ToString();
XmlElement name = xmlDoc.CreateElement("Name");
name.InnerText = d.Name;
XmlElement surname = xmlDoc.CreateElement("Surname");
surname.InnerText = d.Surname;
xe.AppendChild(id);
xe.AppendChild(name);
xe.AppendChild(surname);
root.AppendChild(xe);
}
if (xmlDoc != null)
await xmlDoc.SaveToFileAsync(sf);
But again exception occur in line where I'm opening stream.
thx for your help
Package.Current.InstalledLocation.GetFileAsync represents where you application is installed which is an area you cannot directly write files to. Use the following
Windows.ApplicationModel.Package.Current.InstalledLocation
or
Windows.Storage.ApplicationData.Current.LocalFolder.Path
I am using the former and it works fine, see http://metrorssreader.codeplex.com/SourceControl/changeset/view/18082#263004