I have written a piece of code that parses links from the top navigation from a website.
private string url = "http://www.blah.com/";
private HtmlWeb web;
private HtmlDocument doc;
private string topNavName = "";
private string topNavUrl = "";
public void Setup()
{
try
{
web = new HtmlWeb();
doc = web.Load(url);
web.AutoDetectEncoding = true;
TopCats();
}
catch (Exception e)
{
Console.WriteLine("There has been an issue loading url {0}", e);
}
}
private List<Catalogue> TopCats()
{
List<Catalogue> GetTop = new List<Catalogue>();
try
{
HtmlNodeCollection TopNode = doc.DocumentNode.SelectNodes("//*[#id='TopTabs1_tabs']/li/span/a");
if (TopNode != null)
{
foreach (HtmlNode Topitem in TopNode)
{
topNavName = Topitem.InnerText;
topNavUrl = url + Topitem.Attributes["href"].Value;
Catalogue xmltopcat = new Catalogue();
xmltopcat.indentifier = "here";
xmltopcat.name = topNavName;
xmltopcat.url = topNavUrl;
xmltopcat.description = "";
Console.WriteLine("Category >> {0}",topNavName);
}
}
}
catch (Exception e)
{
Console.WriteLine("There has been an issue Top Nav {0}", e);
}
return GetTop;
}
}
The problem that I am having is that I am not sure how to make each parsed data in the for each loop fill the XML elements. For the mapping on the XML I have created a new class:
class Catalogue
{
[XmlElement("Category identifier")]
public string indentifier
{ get; set; }
[XmlElement("name")]
public string name
{ get; set; }
[XmlElement("url")]
public string url
{ get; set; }
[XmlElement("description")]
public string description
{ get; set; }
}
I am really not sure to create a XML document- I have tried a few things, and I am really am not sure what I am doing. I am still learning C# and this is my first time working with XML.
You can use LINQ to XML.First store your all Catalogues into a List.
Catalogue xmltopcat = new Catalogue();
xmltopcat.indentifier = "here";
xmltopcat.name = topNavName;
xmltopcat.url = topNavUrl;
xmltopcat.description = "";
GetTop.Add(xmltopcat); // <-- add current catalogue to the list
Then call TopCats method and get your list and create XML file:
var list = TopCats();
XElement xDoc = new XElement("Catalogues",
list.Select(c => new XElement("Catalogue",
new XElement("indentifier",c.indentifier)
new XElement("name",c.name)
new XElement("url",c.url)
new XElement("description",c.description)));
xDoc.Save("savepath");
Or you can use XmlSerializer
FileStream fs = new FileStream("records.xml",FileMode.OpenOrCreate,FileAccess.Write);
XmlSerializer serializer = new XmlSerializer(typeof(List<Catalogue>),new XmlRootAttribute("Catalogues"));
serializer.Serialize(fs,list);
Related
Hello everyone recently i have been making a c# app to read a xml file and it worked but now i was tasked with making it do that and read certain nodes from multiple xml files inside a certain folder and now i doesen´t work and shows that error in the title.
using System;
using System.Xml;
using System.IO;
namespace XmlReaderConsoleAPP
{
class Program
{
static void Main()
{
ProcessFile(#"C:\XMLFiles\SaintGobain_Pam_20210118.xml");
try
{
var path = #"C:\XMLFiles\SaintGobain_Pam_20210118.xml";
DirectoryInfo di = new DirectoryInfo(path);
foreach (var file in Directory.GetFiles(path))
{
}
Console.ReadKey();
}
catch(Exception ex)
{
Console.WriteLine("Erro: {0}", ex.Message);
return;
}
static void ProcessFile(string Filename)
{
XmlDocument xml = new XmlDocument();
xml.LoadXml(Filename);
XmlNodeList xnLista = xml.SelectNodes(#"//ImportSession/Batches/batch/Documents/Document/Pages/Page");
Console.WriteLine($"Selected {xnLista.Count} nodes");
int i = 0;
foreach (XmlNode xn in xnLista)
{
Console.WriteLine($"{++i} {xn.Name}: {xn.Attributes["ImportFileName"].Value}");
}
XmlNodeList xnLista2 = xml.SelectNodes(#"//IndexFields/IndexField");
Console.WriteLine($"Selected {xnLista2.Count} nodes");
int j = 0;
foreach (XmlNode xn in xnLista2)
{
Console.WriteLine($"{++j} {xn.Name}: {xn.Attributes["Value"].Value}");
//string error = xn.Attributes["ErrorMessage"]?.Value;
//if (string.IsNullOrEmpty(error))
//{
//}
//elsex
//{
//}
}
Console.WriteLine(Filename);
}
}
}
}
If you guys find the error help me out cause i need it.
Ps: the xml files follow the same roots ImportSession/Batches/Batch/Documents/Document/Pages/Page
Let's first clean up a little:
namespace XmlReaderConsoleAPP
{
class Program
{
static void Main()
{
var path = #"C:\XMLFiles";
var filter = #"*.xml"; // Add filter to only enumerate .xml files
foreach (var file in Directory.EnumerateFiles(path, filter))
{
// Move try/catch inside the loop to skip errornous files.
try
{
ProcessFile( file );
}
catch(Exception ex) // Usually, try to catch the specific as possible
{
Console.WriteLine("Error: {0} {1}in File {2}",
ex.Message, Environment.NewLine, file);
}
}
Console.ReadKey();
}
} // End of Main
static void ProcessFile(string Filename)
{
XmlDocument xml = new XmlDocument();
xml.LoadXml(Filename);
XmlNodeList xnLista = xml.SelectNodes(#"//ImportSession/Batches/batch/Documents/Document/Pages/Page");
Console.WriteLine($"Selected {xnLista.Count} nodes");
int i = 0;
foreach (XmlNode xn in xnLista)
{
Console.WriteLine($"{++i} {xn.Name}: {xn.Attributes["ImportFileName"].Value}");
}
XmlNodeList xnLista2 = xml.SelectNodes(#"//IndexFields/IndexField");
Console.WriteLine($"Selected {xnLista2.Count} nodes");
int j = 0;
foreach (XmlNode xn in xnLista2)
{
Console.WriteLine($"{++j} {xn.Name}: {xn.Attributes["Value"].Value}");
}
Console.WriteLine(Filename);
}
} // class
} // namespace
Next: System.Xml.XmlException means there is something wrong with the xml input file.
What can you do about that?
Skip it, so the others may still be processed. Log the error, so you can later deep dive into the file, or request it be fixed and sent again.
If you have an XML Schema, you can validate the xml and easier find what exactly is wrong. See XML schema (XSD) validation with XmlSchemaSet and/or XmlDocument.Validate Method.
You can examine the input file manually and find the error. Mind that the message may sometimes be deceiving. I'd start with checking if it is well-formed and valid xml (there are tools for that).
I was able to resolve the problem with objects and their serialization.
You can find a way to do it with these two posts:
Objects:https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/objects
Objects serialization:https://learn.microsoft.com/en-us/dotnet/standard/serialization/how-to-serialize-an-object
Giving some more context.
Start by making empty strings at the start of the method you're doing, it being a foreach loop or a if statement
class Program
{
static DataAccess da = new DataAccess();
public static void Main()
{
XmlSerializer serializer = new XmlSerializer(typeof(ImportSession));
foreach (string filename in Directory.EnumerateFiles(Properties.Settings.Default.PastaXML, "*.xml"))
{
string fName = "";
string BatchCName = "";
string batchName = "";
string description = "";
ProcessFile(filename, serializer, fName, BatchCName, batchName, description );
}
Console.ReadKey();
}
}
After that start in my case my processfile function
private static void ProcessFile(string filename, XmlSerializer serializer, string fName, string batchName, string description, string BatchCName)
{
Console.WriteLine("A processar xml: " + filename);
bool temErro = false;
using (FileStream file = File.OpenRead(filename))
{
var session = (ImportSession)serializer.Deserialize(file);
foreach (Batch batch in session.Batches)
{
fName = Path.GetFileName(filename);
BatchCName = batch.BatchClassName;
batchName = batch.Name;
description = batch.Description;
foreach (Document doc in batch.Documents)
{
foreach (Page page in doc.Pages)
{
# if (!string.IsNullOrEmpty(batch.Processed.ToString()))
{
if (page.HasError)
{
string Import = page.ImportFileName;
Console.WriteLine("Página com erro:" + Import + fName);
temErro = true;
da.SP_Insert(filename,fName,BatchCName,batchName,description,1,Import,0, "");
There are two if statements inside this processfile that run checks on if there is a error inside the file and if the file as already been processed.
I also added Insert into a stored procedure to make sure everything is complete in this edit I'm making.
The objects I used are as follows
public class ImportSession
{
public Batch[] Batches { get; set; }
}
public class Batch
{
[XmlAttribute]
public string Name { get; set; }
[XmlAttribute]
public string Description { get; set; }
[XmlAttribute]
public string BatchClassName { get; set; }
[XmlAttribute]
public bool Processed { get; set; }
public Document[] Documents { get; set; }
}
public class Document
{
[XmlAttribute]
public string FormTypeName { get; set; }
public IndexField[] IndexFields { get; set; }
public Page[] Pages { get; set; }
}
public class IndexField
{
[XmlAttribute]
public string Name { get; set; }
[XmlAttribute]
public string Value { get; set; }
}
public class Page
{
[XmlAttribute]
public string ImportFileName { get; set; }
[XmlAttribute]
public string ErrorCode { get; set; }
[XmlAttribute]
public string ErrorMessage { get; set; }
[XmlIgnore]
public bool HasError => !string.IsNullOrWhiteSpace(ErrorMessage);
}
And my stored procedure insert in case any of you are wondering how to do it
public void SP_Insert(string XMLPath, string XMLName, string BatchClassName, string BatchName,
string BatchDescription, int Error, string ErrorImagePath, int Done, string DonePath)
{
try
{
ManageConnectionState();
SqlCommand command = new SqlCommand("Sp_Insert", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#XMLPath",SqlDbType.NText).Value = XMLPath;
command.Parameters.Add("#XMLName",SqlDbType.NText).Value = XMLName;
command.Parameters.Add("#BatchClassName",SqlDbType.NText).Value= BatchClassName;
command.Parameters.Add("#BatchName",SqlDbType.NText ).Value = BatchName;
command.Parameters.Add("#BatchDescription", SqlDbType.NText ).Value = BatchDescription;
command.Parameters.Add("#Error",SqlDbType.Bit).Value = Error;
command.Parameters.Add("#ErrorImagePath", SqlDbType.NText).Value = ErrorImagePath;
command.Parameters.Add("#Done", SqlDbType.Bit ).Value=Done;
command.Parameters.Add("#DonePath", SqlDbType.NText).Value = DonePath;
command.ExecuteScalar();
}
catch (Exception ex)
{
Console.WriteLine("Erro: " + ex.Message);
}
finally
{
ManageConnectionState();
connection.Close();
}
}
Please comment if you don´t understand something ill help out.
I'm trying to upload files to a folder using SharePoint and C#.
I managed to create folders with my code and it works fine.
This is my Document class:
[DataContractAttribute]
public class Document
{
[DataMemberAttribute]
public string Name { get; set; }
[DataMemberAttribute]
public byte[] Content { get; set; }
[DataMemberAttribute]
public bool ReplaceExisting { get; set; }
[DataMemberAttribute]
public string Folder { get; set; }
[DataMemberAttribute]
public Dictionary<string, object> Properties { get; set; }
public Document()
{
Properties = new Dictionary<string, object>();
}
public Document(string name, byte[] content)
{
Name = name;
ReplaceExisting = false;
Content = content;
Properties = new Dictionary<string, object>();
}
public Document(string name, byte[] content, bool replace)
{
Name = name;
Content = content;
ReplaceExisting = replace;
Properties = new Dictionary<string, object>();
}
}
And this is the class where I use it to upload files (Document) to an existing share point folder:
public class SharePointHandler : IDisposable
{
private static string sharePointSite = "My Site";
private static string documentLibraryName = "Root folder";
public SharePointHandler() { }
public void Upload(List<Document> documents, string company, int year, string quarter)
{
string Year = year.ToString();
try
{
using (ClientContext context = new ClientContext(sharePointSite))
{
var list = context.Web.Lists.GetByTitle(documentLibraryName);
context.Load(list);
var root = list.RootFolder;
context.Load(root);
context.ExecuteQuery();
.
.
.
foreach (var document in documents)
{
var fileCreationInformation = new FileCreationInformation();
fileCreationInformation.Content = document.Content;
fileCreationInformation.Overwrite = true;
fileCreationInformation.Url = list.RootFolder.ServerRelativeUrl + "/" + company + "/" + Year + "/" + quarter + "/" + document.Name;
Microsoft.SharePoint.Client.File uploadFile = quarterFolder.Files.Add(fileCreationInformation);
foreach (KeyValuePair<string, object> property in document.Properties)
uploadFile.ListItemAllFields[property.Key] = property.Value;
try
{
uploadFile.CheckOut();
context.ExecuteQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
uploadFile.ListItemAllFields.Update();
context.ExecuteQuery();
uploadFile.CheckIn("", CheckinType.MajorCheckIn);
context.ExecuteQuery();
}
}
}
catch (Exception ex)
{
EventLog.WriteEntry(ex.Message, EventLogEntryType.Error);
return;
}
}
public void Dispose() { }
}
When I run the code I have one document with:
Content: {byte[11430]}
Folder: null
Name: Testing.docx
Properties: Count = 0
ReplaceExisting: false
Everything works fine and I get the URL needed.
But when I get to these commands:
try
{
uploadFile.CheckOut();
context.ExecuteQuery();
}
The program falls and I get error that says: File not found.
What am I doing wrong?
Thank you for your help!
Here is a working example of an upload to SharePoint via CSOM:
using (ClientContext conext = new ClientContext(site.url))
{
List projectFiles = projects.Web.Lists.GetByTitle("Project Files");
context.Load(projectFiles.RootFolder, w => w.ServerRelativeUrl);
context.ExecuteQuery();
FileStream documentStream = System.IO.File.OpenRead(filePath);
byte[] info = new byte[documentStream.Length];
documentStream.Read(info, 0, (int)documentStream.Length);
string fileURL = projectFiles.RootFolder.ServerRelativeUrl + "/Folder/FileName.ext";
FileCreationInformation fileCreationInformation = new FileCreationInformation();
fileCreationInformation.Overwrite = true;
fileCreationInformation.Content = info;
fileCreationInformation.Url = fileURL;
Microsoft.SharePoint.Client.File uploadFile = projectFiles.RootFolder.Files.Add(fileCreationInformation);
context.Load(uploadFile, w => w.MajorVersion, w => w.MinorVersion);
context.ExecuteQuery();
}
In your case, I would upload the file and ExecuteQuery() and then add your metadata and execute a second query, make sure you add a context.Load after your files.Add(). You are trying to do too many things at once, so just use this code to get the file uploaded and work your way through your other needs after. Also, the file add will not create folders for you so make sure you are specifying a valid path.
i'm having a trouble with taking information from xml using linq in c# wpf application.
followings are the codes i use.
public class YouTubeInfo
{
public string LinkUrl { get; set; }
public string EmbedUrl { get; set; }
public string ThumbNailUrl { get; set; }
public string Title { get; set; }
public int Duration { get; set; }
}
public class YouTubeProvider
{
const string SEARCH = "http://gdata.youtube.com/feeds/api/videos?q={0}&alt=rss&start-index={1}&max-results={2}&v=1";
const string Most_popular = "http://gdata.youtube.com/feeds/api/standardfeeds/KR/most_popular?time=today&alt=rss&start-index={1}&max-results={2}&v=2";
//const string Entertainment = "https://gdata.youtube.com/feeds/api/standardfeeds/KR/most_popular_Entertainment?start-index=1&max-results=2";
#region Load Videos From Feed
public static int search_based;
static string search;
public static List<YouTubeInfo> LoadVideosKey(string keyWord, int start, int limit)
{
try
{
switch (search_based)
{
case 0: search = SEARCH; break;
case 1: search = Most_popular; break;
}
var xraw = XElement.Load(string.Format(search, keyWord, start, limit));
var xroot = XElement.Parse(xraw.ToString());
var links = (from item in xroot.Element("channel").Descendants("item")
select new YouTubeInfo
{
LinkUrl = item.Element("link").Value,
Title = item.Element("title").Value,
EmbedUrl = GetEmbedUrlFromLink(item.Element("link").Value),
ThumbNailUrl = GetThumbNailUrlFromLink(item),
Duration = GetDuration(item),
}).Take(limit);
return links.ToList<YouTubeInfo>();
}
catch (Exception e)
{
Trace.WriteLine(e.Message, "ERROR");
}
return null;
}
i want to take information from this xml
https://gdata.youtube.com/feeds/api/standardfeeds/KR/most_popular_Entertainment?start-index=1&max-results=2
Maybe better if you use SyndicationFeed. See the sample below:
Import needed namspaces
using System.ServiceModel.Syndication;
using System.Xml;
Load feed implementation
private static string GetAttributeFromGroup(SyndicationElementExtensionCollection seec, string elementName, string attributeName)
{
foreach (SyndicationElementExtension extension in seec)
{
XElement element = extension.GetObject<XElement>();
if (element.Name.LocalName == "group")
{
foreach (var item in element.Elements())
{
if (item.Name.LocalName == elementName)
{
return item.Attribute(attributeName).Value;
}
}
}
}
return null;
}
public static List<YouTubeInfo> LoadVideosKey(string keyWord, int start, int limit)
{
try
{
switch (search_based)
{
case 0: search = SEARCH; break;
case 1: search = Most_popular; break;
}
var xDoc = XmlReader.Create(string.Format(search, keyWord, start, limit));
SyndicationFeed feed = SyndicationFeed.Load(xDoc);
var links = (from item in feed.Items
select new YouTubeInfo
{
LinkUrl = item.Id,
Title = item.Title.Text,
EmbedUrl = item.Links.FirstOrDefault().Uri.AbsoluteUri,
ThumbNailUrl = GetAttributeFromGroup(item.ElementExtensions, "thumbnail", "url"),
Duration = int.Parse(GetAttributeFromGroup(item.ElementExtensions, "duration", "seconds") ?? "0"),
}).Take(limit);
return links.ToList<YouTubeInfo>();
}
catch (Exception e)
{
Trace.WriteLine(e.Message, "ERROR");
}
return null;
}
You can learn more about SyndicationFeed here
Your basic code is actually working fine. You did not post code for GetThumbnailUrlFromLink and for GetDuration, but I suspect you are having trouble with namespaces. See this answer for a sample of using namespaces.
Essentially, if you added:
static XNamespace nsMedia = "http://search.yahoo.com/mrss/";
static XNamespace nsYt = "http://gdata.youtube.com/schemas/2007";
then your Duration could look like:
Duration = (int)item.Element(nsMedia + "group").Element(nsYt + "duration").Attribute("seconds")
I stomped on some very weird bug which is very hard to reproduce I literally cant reproduce it. We have a window service installed on around 300+ PCs. From time to time config file(xml) that is used by this service become clear (on some of them). Totally clear no xml tags, nothing, 0kb. I have no clue what can cause such problem. No exception is logged in our logs. Even after this config becoming clear it's still running however it's not communicating with our web service. This is the class that is used for xml serialization and deserialization. I can’t find what can be possibly causing such behavior. Of course problem might not be in this particular class. Any suggestions?? Maybe some hints what can cause a file to become clear. When any operation on this file is by using this class.
Sorry for my bad English.
[XmlRootAttribute("xmlconfig", Namespace = "DSD_Config", IsNullable = false)]
public class xmlconfig
{
[XmlElementAttribute(IsNullable = false)]
public string ProgramApteczny { get; set; }
public string Server { get; set; }
public string Database { get; set; }
public string User { get; set; }
public string Password { get; set; }
public string DSDUser { get; set; }
public string DSDPassword { get; set; }
public string DSDServerAdres { get; set; }
//public static string cofFile = System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\DSD_Agent\\config.xml";
public static string cofFile = Application.StartupPath + "\\config.xml";
public xmlconfig()
{
}
public xmlconfig(string sProgramApteczny, string sServer, string sDatabase, string sUser, string sPassword, string sDSDUser, string sDSDPassword, string sDSDServerAdres)
{
ProgramApteczny = sProgramApteczny;
Server = sServer;
Database = sDatabase;
User = sUser;
Password = sPassword;
DSDUser = sDSDUser;
DSDPassword = sDSDPassword;
DSDServerAdres = sDSDServerAdres;
}
public static void readXMLConfig(out xmlconfig configFile)
{
XmlSerializer oSerializer = new XmlSerializer(typeof(xmlconfig));
configFile = new xmlconfig();
try
{
using (FileStream fs = new FileStream(cofFile, FileMode.Open, FileAccess.Read))
{
configFile = (xmlconfig)oSerializer.Deserialize(fs);
try
{
configFile.Password = Encryption.DecryptString(configFile.Password);
}
catch (Exception)
{
configFile.Password = configFile.Password;
}
try
{
configFile.DSDPassword = Encryption.DecryptString(configFile.DSDPassword);
}
catch (Exception)
{
configFile.DSDPassword = configFile.DSDPassword;
}
}
}
catch
{
configFile = null;
}
}
public static void writeXMLConfig(string sProgramApteczny, string sServer, string sDatabase, string sUser, string sPassword, string sDSDUser, string sDSDPassword)
{
xmlconfig oxmlconfig = new xmlconfig();
readXMLConfig(out oxmlconfig);
sPassword = Encryption.EncryptString(sPassword);
sDSDPassword = Encryption.EncryptString(sDSDPassword);
if (oxmlconfig == null)
{
oxmlconfig = new xmlconfig(sProgramApteczny, sServer, sDatabase, sUser, sPassword, sDSDUser, sDSDPassword, "");
}
else
{
oxmlconfig.ProgramApteczny = sProgramApteczny;
oxmlconfig.Server = sServer;
oxmlconfig.Database = sDatabase;
oxmlconfig.User = sUser;
oxmlconfig.Password = sPassword;
oxmlconfig.DSDUser = sDSDUser;
oxmlconfig.DSDPassword = sDSDPassword;
}
XmlSerializer oSerializer = new XmlSerializer(typeof(xmlconfig));
TextWriter oStreamWriter = null;
try
{
oStreamWriter = new StreamWriter(cofFile, false);
oSerializer.Serialize(oStreamWriter, oxmlconfig);
}
catch (Exception oException)
{
WriteToLog(DateTime.Now, "Aplikacja wygenerowała następujący wyjątek: " + oException.Message);
// Console.WriteLine("Aplikacja wygenerowała następujący wyjątek: " + oException.Message);
}
finally
{
if (null != oStreamWriter)
{
oStreamWriter.Close();
}
}
}
public static void writeXMLDSDConfig(string sDSDServerAdres)
{
xmlconfig oxmlconfig = new xmlconfig();
readXMLConfig(out oxmlconfig);
if (oxmlconfig == null)
{
throw new Exception("Aplikacja wygenerowała następujący wyjątek: Musisz zdefiniować wszystkie parametry");
}
else
{
oxmlconfig.DSDPassword = Encryption.EncryptString(oxmlconfig.DSDPassword);
oxmlconfig.Password = Encryption.EncryptString(oxmlconfig.Password);
oxmlconfig.DSDServerAdres = sDSDServerAdres;
}
XmlSerializer oSerializer = new XmlSerializer(typeof(xmlconfig));
TextWriter oStreamWriter = null;
try
{
oStreamWriter = new StreamWriter(cofFile, false);
oSerializer.Serialize(oStreamWriter, oxmlconfig);
}
catch (Exception oException)
{
throw new Exception("Aplikacja wygenerowała następujący wyjątek: " + oException.Message);
}
finally
{
if (null != oStreamWriter)
{
oStreamWriter.Close();
}
}
}
}
What I guess, the xml file is accessed by multiple computers/windows services; if so?
Looks no locking mechanism is being used while reading and writing the file. a possible work around would be using a single instance class that only allows one thread to read/write file at one time.
bool isInProgress=false
Public void Read()
{
if(isInProgress==false)
{
isInProgress=true;
try
{
//Do reading or writing
}
finally
{
isInProgress=false;
}
}
}
I will add a new node to parent node on my xml file. Unit test for this code says "success", it is passing but no added node in xml.
Also, some of tests i'm getting the error;
<< Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) >>
on the line SaveToFileAsync
what is wrong with me? and there is an alternative way to do this?
public string ConnectionPath { get; set; }
protected string XPath { get; set; }
protected string XParentPath { get; set; }
protected XmlDocument Source { get; set; }
protected StorageFolder SFolder { get; set; }
protected StorageFile SFile { get; set; }
public RepositoryBase(string connectionPath)
{
this.ConnectionPath = connectionPath;
}
public async void Insert(T entity)
{
SFolder = Package.Current.InstalledLocation;
SFile = await SFolder.GetFileAsync(this.ConnectionPath);
var content = await FileIO.ReadTextAsync(SFile);
if (!string.IsNullOrEmpty(content))
{
Source = new XmlDocument();
Source.LoadXml(content);
}
var tagName = typeof(T).Name;
if (tagName != null)
{
IXmlNode parentNode = Source.SelectSingleNode(XParentPath);
if (parentNode != null)
{
XmlElement newNode = Source.CreateElement(tagName);
newNode.InnerText = GetContent(entity);
parentNode.AppendChild(newNode);
}
}
await Source.SaveToFileAsync(SFile);
}
* PlaceRepositoryClass ;
public class PlaceRepository : RepositoryBase<Place>
{
public PlaceRepository()
: base("Data\\bla\\bla.xml")
{
XPath = "/Country[Id=1]/Cities/City[Id=1]/Places/Place";
XParentPath = "/Country[Id=1]/Cities/City[Id=1]/Places";
}
}
Unit Test Method ;
[TestMethod]
public void AppendNode()
{
Place place = new Place()
{
Id = 40,
Name = "xxxxx",
SummaryPath = "yyyyy",
Logo = "xy.png",
LogoSmall = "xy_small.png",
Latitude = "32.423",
Longitude = "34.23424",
Content = new PlaceContent() { Items = new List<ContentItem>() { new ContentItem() { TextPath = "aaaa", Header = "bbbbb", AudioFilePath = "x.mp3" } } },
Gallery = new PhotoGallery() { Photos = new List<Photo>() { new Photo() { Path = "ab.png", Text = "abab" } } }
};
PlaceRepository repository = new PlaceRepository();
repository.Insert(place);
}
You are trying to write to a file that's part of the application package, and that's read only. You could copy the file to local storage and make the modifications there perhaps.