Parsing XML file in Xamarin Android - c#

I am fairly new to developing for android using Xamarin.
I am making an application that translates dietary requirements into other languages and I am trying to load the options that one can input when making a translation.
To do this the text is put into a list after I have read the XML file:
XmlDocument LifeStyles = new XmlDocument();
LifeStyles.Load("engLifestyles.xml");
and the xml is located here:
File Location In Project
However i keep getting this error where the file is named when i run the app:
Unhandled Exception:
System.IO.FileNotFoundException: Could not find file "/engLifestyles.xml". occurred.
Any help will be much appreciated. Thank you in advanced.

In Xamarin.Android project you have to save your file in Assets folder, then you can load it. Assets folder in Xamarin is way to include arbitary files like text, xml, music etc.
Asstes folder files are readonly so if you try to write to your xml file you will get System.UnauthorizedAccessException
So your code should look like this:
XmlDocument LifeStyles = XmlDocument.Load(Assets.Open("engLifestyles.xml"));
or you can use AssetsManager too:
AssetManager assets = this.Assets;
XmlDocument LifeStyles = XmlDocument.Load(assets .Open("engLifestyles.xml"));

Here's the solution I ended up using. First, place the xml file into the Assets directory. Open it's properties and mark it's Build Action as AndroidAsset. Mark it's Copy to Output Directory as Copy if newer or some such. These will ensure your xml file is readable and is shipped with your package.
After all of that, you can then do this. In my case I wanted to load a bunch of strings into a dictionary.
private async void LoadStrings()
{
try
{
using (Stream stream = await FileSystem.OpenAppPackageFileAsync(STRING_FILE))
{
XmlDocument localInfo_Xml = new XmlDocument();
localInfo_Xml.Load(stream);
XmlNodeList tagList = localInfo_Xml.GetElementsByTagName(STRING_KEY);
foreach (XmlElement xmlElement in tagList)
{
string name = xmlElement.GetAttribute(NAME_KEY);
string value = xmlElement.InnerText;
strings.Add(name, value);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw ex;
}
}
Hope that helps someone else's day get better.

Related

Read an xml file from non-web project in C# (Visual Studio)

I am trying to read an xml file that is present in one of the projects in my VS solution. Here's my code.
string path = HttpContext.Current.Server.MapPath(#"~\Resources\XmlDocument.xml");
XDocument document = XDocument.Load(path);
This works fine if my xml file is in the web project. But in reality I have my xml file in a different project under the same solution.
I cannot use Server.MapPath as this searches web project. I searched for an answer but did not find any solution that worked for me.
How can I access this xml file? I am trying to access this from a helper method in the same project.
Try this:
string path = HostingEnvironment.ApplicationPhysicalPath + (some path);
public void LoadXML()
{
if (System.IO.File.Exists(path))
{
XmlSerializer serializer = new XmlSerializer(typeof(List<int>));
lock (new object())
{
using (TextReader reader = new StreamReader(path))
{
return (List<int>)(serializer.Deserialize(reader));
}
}
}
}
this is working for me.
Once you get your current directory, why not just navigate up a number of parent directories and then locate your file?
DirectoryInfo info = new DirectoryInfo(Environment.CurrentDirectory);
DirectoryInfo parent = info.Parent.Parent;
string file = Path.Combine(parent.FullName, #"your\path");
Here I use Environment.CurrentDirectory to get where the program is at now, but you can stack as many Parent elements as you need. Then you can combine the path to get to your file in the other project.
EDIT:
Once your application is running all the environment variables and Server.MapPath will give you the location that it is executing from (i.e. the path you are getting now). In light of this it may be easier to create a folder and reference this via it's full path. (C:\Data\myfile.xml)

Issues with saving xml document to xml file in the output directory. c# Xamarin

I'm making an application that loads and saves profile nodes to an external xml document in my output directory. It worked fine when I was opening it from my Assets folder but since that is read only (I think) I need to have it read and write from the output directory or another folder.
Like this:
XmlDocument users = new XmlDocument();
users.Load("users.xml");
However I get this error when this code runs:
"System.IO.FileNotFoundException: Could not find file "/users.xml"."
I've ticked the secondary storage permissions but i'm still a bit confused about just referencing a file in the output directory.
Would also appreciate the help for saving too as I assume the same error will occur:
users.DocumentElement.AppendChild(user);
users.Save("users.xml");
Thank you in advance.
In xamarin form you can try this code to load xml file from PCL project.
var assembly = typeof(TestClass).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream(“PrjectName.FileName”);
using (var reader = new System.IO.StreamReader(stream))
{
var serializer = new XmlSerializer(typeof(List<BuildOptions>)); var listData = (List<T>)serializer.Deserialize(reader);
}

Loading resources from another project?

I'm trying to load an XML file from a separate project; One of these projects is a game engine, which calls the XML document reader and takes in a path specifying the relative directory to the file.
From Engine
XDocument doc;
try
{
Stream stream = this.GetType().Assembly.GetManifestResourceStream(path);
doc = XDocument.Load(stream);
}
catch
{
doc = XDocument.Load(path);
}
From the other project
string filePath = "Test.xml";
Npc npc = new Npc("somename", 2,filePath);
Test.xml resides in the other project's root directory. The Npc constructor makes a call to a Statistics object constructor, which then calls the method which loads the XDocument. As this is happening, the filePath is simply passed downward through the layers.
I've looked at this, and tried the embedded resource example, which is ultimately what I'm trying to accomplish, and it didn't work for me.
What am I doing wrong, here?
Update
I changed Text.xml to Chronos.Text.xml, as that is where the file resides. In my debugger, I see that the stream simply returns null when I use that as a path:
try
{
Stream stream = this.GetType().Assembly.GetManifestResourceStream("Chronos.Test.xml"); //returns null
doc = XDocument.Load(stream); //Exception thrown
}
catch
{
doc = XDocument.Load(path); //File not found
}
Embeded resources are embeded directly in the executable. Assembly.GetManifestResourceStream() is trying to open a stream on the embeded resource, what you should be providing is the resource name in the following format AssemblyDefaultNamespace.Directory.Filename.
If you are trying to open an XML file from another directory, you will have to provide the full path to XDocument.Load(), or a path relative from your current project output directory pointing to that other directory.
Another solution would be to copy the data from the other project into your project and specify that you want the file to be copied to your output directory.

How to load an XML file from a file in the solution, build with Embedded Resource?

Here's an outline of my solution:
I've set the build to Embedded Resource and when I generate the application the XML file doesn't appear in the /Release folder. This is correct, I want this behavior.
Now I'm trying to load that file into an XDocument so I can parse the data within:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Parsing XML.");
XDocument championXml = XDocument.Load("Champions.xml");
Console.ReadKey();
}
}
And I get a file not found error because it's trying to find the xml file in the full path of the release folder.
How can I properly load this data into my XDocument?
Reference the resource property directly and use Parse instead of load:
XDocument championXml = XDocument.Parse(Properties.Resources.ChampionsXML);
^^^^^^^^^^^^
//Name of your resource |
The namespace will be somewhat different depending on your project structure.
Use GetManifestResourceStream():
var asm = Assembly.GetExecutingAssembly();
using(var stream = asm.GetManifestResourceStream("Namespace.Champions.xml"))
{
// ...
}
The exact names used to reference resources can be found by calling GetManifestResourceNames().
You should get stream from assembly:
Assembly.GetExecutingAssembly().GetManifestResourceStream(name)
Where name will be something like: 'LinqToXml.Champions.xml'

Getting file path in ASP.NET and XDocument.Load

I have a static class in a folder off root in my solution. In that static class' folder, there's a subfolder containing XML files. So I've got these files:
/PartialViews/Header/MyStaticClass.cs
/PartialViews/Header/Config/en-US.xml
/PartialViews/Header/Config/jp-JP.xml
...
I'm having trouble using XDocument.Load() with those XML files. Specifically, I'm trying to load the XML files from the static constructor of MyStaticClass.
XDocument.Load() can't seem to find the files, however. I've tried all these and none work:
static MyStaticClass()
{
XDocument doc;
// These all throw exceptions relating to directory not found
doc = XDocument.Load("/Config/en-US.xml");
doc = XDocument.Load(#"\Config\en-US.xml");
doc = XDocument.Load("/PartialViews/Header/Config/en-US.xml");
doc = XDocument.Load(#"\PartialViews\Header\Config\en-US.xml");
}
I also tried using Assembly.GetExecutingAssembly().Location and Assembly.GetEntryAssembly().Location before the relative path, but the assembly resolved by Assembly is always a .NET library (because the type is being initialized?).
How can I load the file without changing its location in the solution?
In ASP.NET you should use Server.MapPath() to find all local files.
string relPath = "~/PartialViews/Header/Config/en-US.xml";
string absPath = Server.MapPath(relPath);
XDocument doc = XDocument.Load(absPath);
For .NET web apps use
HttpContext.Current.Server.MapPath("~/"); this will get you the root directory of the executing file.

Categories