Save xml file in Windows Store application - c#

I want to save xml file, but I get error messages. Regarding the documentation
I should use a class in the Windows.Storage, but I don't know which class I should use and how to use it.
string filename;
XDocument doc = XDocument.Load(filename);
...
doc.Save(filename);
Error: Argument 1: cannot convert from 'string' to 'System.IO.Stream'
Error: The best overloaded method match for 'System.Xml.Linq.XDocument.Save(System.Xml.XmlWriter)' has some invalid arguments

StorageFile file = await StorageFile.GetFileFromPathAsync(filename);
using (Stream fileStream = await file.OpenStreamForWriteAsync())
{
doc.Save(fileStream);
}

Related

Convert XmlWriter to Stream / char / byte []

I have an asp.net/C#/Blazor environment, where a button generates an XML with a specific class. With XML Writer, I can make the file, and even can save/download it, but it goes to the server-side (It must to be downloaded on client-side. please, do not argue about it).
I know Blazor implemented some instant download (https://learn.microsoft.com/en-us/aspnet/core/blazor/file-downloads?view=aspnetcore-6.0) and it works perfect with blank/new files, but the problem is, I don't know how to "pass" or convert my previously generated XML with XML Writer method, because Blazor method(s) only allow Stream, char or byte Arrays downloads.
When I tried to convert it, the error
Some of my code is:
protected async Task CreateXmlFile(int correlativo,string idDocumento, string siglaDocumento, List<DocumentoXML> documentos = null, List<SignersXML> signersXMLs = null,
List<ContentXMLComplemento> complementos = null,
List<SignersXMLComplemento> signersComplemento = null)
{
_xmlWriterSettings = new XmlWriterSettings
{
Indent = true,
Encoding = new UTF8Encoding(false)
};
string fullPath= "";
XmlWriter writer;
XmlSerializer serializer;
var documentoIngresoRaiz = new DocumentoIngresoRaiz
{
Content_XML = new List<ContentXML>
{
new ContentXML
{
sve_XML = new List<sveXML>
{
new sveXML
{
Documento_XML = documentos
}
}
}
},
Signers_XML = signersXMLs
};
fullPath = $"{mainPath}Ingreso-{correlativo}.xml";
var fileName = $"Ingreso-{correlativo}.xml";
writer = XmlWriter.Create(fullPath, _xmlWriterSettings);
serializer = new XmlSerializer(typeof(DocumentoIngresoRaiz));
serializer.Serialize(writer, documentoIngresoRaiz);
writer.Close();
//I've been trying with these 3 Blazor method lines, to send my xml as stream
var fileStream = new MemoryStream(writer);
using var streamRef = new DotNetStreamReference(stream: fileStream);
await JS.InvokeVoidAsync("downloadFileFromStream", fileName, streamRef);
}
Error CS1503: Argument 1: cannot convert from 'System.Xml.XmlWriter' to 'byte[]'
I've been looking all around StackOverflow and the Internet with no success.
I found some similar posts (I want to download XML file in C# which I created using XmlWriter.Create() on user's system) (How to get a Stream from an XMLWriter?), but they couldn't solve my problem. Any help or tip is welcome. Thank you in advance!
Since there was no way to convert the already generated XML file to byte/stream/char array, I found out that the solution was:
saving this XML file on server-side
and then immediately download it to local machine, via JavaScript code (pasted below), passing the fileURL (location of file on the server) and fileName (name of the file)
await JS.InvokeVoidAsync("triggerFileDownload", fileName, fileURL);
function triggerFileDownload(fileName, url) {
const anchorElement = document.createElement('a');
anchorElement.href = url;
anchorElement.download = fileName ?? '';
anchorElement.click();
anchorElement.remove();
}

How to give xml file path in XDocument.Load method in UWP C#

I have an XML file at Assets/Fonts/FontAwsome_version5.xml and I tried reading this file using the following method but it's giving an error - uri prefix is not recognized
XDocument xmlDocument = XDocument.Load(filePath); string filePath = "ms-appx:///Assets/Fonts/FontAwsome_version5.xml";
How to give xml file path in XDocument.Load method in UWP C#
I'm afraid you can't load the file with UWP uri scheme for System.Xml.Linq namespace api, for the requirement, you could use Windows Storage Api to open the file as stream then call XDocument load stream method to access the file's xml content. For the testing the following code could work directly.
private async void Button_Click(object sender, RoutedEventArgs e)
{
string filePath = "ms-appx:///Assets/Font.xml";
var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(filePath));
using (var stream = await file.OpenStreamForReadAsync())
{
XDocument xmlDocument = XDocument.Load(stream);
}
}

How do I specify a type argument explicitly when reading an XML file in UWP

I am working on a UWP app where I need to read and write an XML file to the device. It took me a while of searching to find a tutorial that covered the basics well enough for me to "sort of" understand it. This tutorial Serialize/Deserialize an Object to an XML File (Windows Universal apps 8.1) has a succinct example that according to the comments should work. However I am getting this error when I F5 it The type arguments for method cannot be inferred from the usage. Try specifying the type arguments explicitly.
The error surfaces on this line
Robot robot2 = await XmlIO.XmlRW.ReadObjectFromXmlFileAsync("robbie.xml");
The method that it points to is this
public static async Task<T> ReadObjectFromXmlFileAsync<T>(string filename)
{
// this reads XML content from a file ("filename")
// and returns an object from the XML
T objectFromXml = default(T);
var serializer = new XmlSerializer(typeof(T));
StorageFolder folder = ApplicationData.Current.LocalFolder;
StorageFile file = await folder.GetFileAsync(filename);
Stream stream = await file.OpenStreamForReadAsync();
objectFromXml = (T)serializer.Deserialize(stream);
stream.Dispose();
return objectFromXml;
}
I thought that maybe I needed to change the Task < T > to a Task < string > but I couldn't make that work either. So what do I need to do to specify the type argument explicitly?
The compiler can't determine what type T will be. You need to specify it explicitly:
Robot robot2 = await XmlIO.XmlRW.ReadObjectFromXmlFileAsync<Robot>("robbie.xml");

XmlException in C#: Data at the root level is invalid

I'm trying to read an XML file in a C# WinRt app when the app resumes:
Windows.Storage.StorageFile File = await Windows.Storage.ApplicationData.Current.TemporaryFolder.GetFileAsync("PreviousSession.xml");
if (File != null)
{
var File2 = await Windows.Storage.ApplicationData.Current.TemporaryFolder.GetFileAsync("PreviousSession.xml");
string Document = File2.ToString();
System.Xml.Linq.XDocument.Parse(Document);
}
But I get a System.Xml.XmlException:
Data at the root level is invalid. Line 1, position 1.
How can I fix this and read the file properly?
My XML document is being constructed like this:
Windows.Data.Xml.Dom.XmlDocument Document = new Windows.Data.Xml.Dom.XmlDocument();
Windows.Data.Xml.Dom.XmlElement Element = (Windows.Data.Xml.Dom.XmlElement)Document.AppendChild(Document.CreateElement("PreviousSessionData"));
...
Windows.Storage.IStorageFile TempFile = await Windows.Storage.ApplicationData.Current.TemporaryFolder.CreateFileAsync("PreviousSession.xml", Windows.Storage.CreationCollisionOption.ReplaceExisting);
await Document.SaveToFileAsync(TempFile);
For a file like this:
<PreviousSessionData>...</PreviousSessionData>
System.Xml.Linq.XDocument.Parse expects an XML string, not an XML File name.
This code is wrong (see comments) :
string Document = File2.ToString(); // Return the name of "File2" object, not File2 content!
System.Xml.Linq.XDocument.Parse(Document); // Parse error, trying to parse the string "PreviousSession.xml" !
What you want is put the content of the file in a string:
string Document = File.ReadAllLines(File2);
System.Xml.Linq.XDocument.Parse(Document);
Or you can use XDocument.Load which expects a file path, not a string.

System.XML and Encoding trouble

I have an application which is using to create XML documents on the example of existing. But that's not the point. Today I noticed that there is an error if the opened file encoding is ANSI. Before that I worked with files UTF-8 and this problem does not arise. What should you do and how?
Fragments of code:
string filepath;
XmlDocument xdoc = new XmlDocument();
XmlElement root;
...............
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
filepath = openFileDialog1.FileName;
textBox1.Text = filepath;
load();
}
...............
public void load()
{
xdoc.Load(filepath);
root = xdoc.DocumentElement;
...............
Error:
An unhandled exception of type 'System.Xml.XmlException' occurred in
System.Xml.dll Additional information: An invalid character for the
specified encoding., Line 35, position 16.
In that line is Cyrillic symbols (russian language). But if I converted this document to UTF-8 by NotePad++ - it loaded correctly.
You could use a StreamReader to read the file with the correct encoding and then load that stream into the XmlDocument overload that accepts a stream.
using(var sr = new StreamReader(filepath, myEncoding))
{
xdoc.Load(sr);
}
You can obtain myEncoding via the GetEncoding method.

Categories

Resources