我正在尝试使用Linq将一些更改保存回XML文件,我在SO和教程网站上看到很多这样的例子,但是由于某些原因我在xmlDoc.Save(customerXMLPath)上收到错误; line 参数1:无法转换为' string'到' System.IO.Stream' 。
我见过的大多数样本都是ASP.Net样本,但我不认为这会对语法产生很大影响(这是一个UWP应用程序)。有人可以告诉我我做错了吗?
private void SaveChange_Click(object sender, RoutedEventArgs e)
{
string customerXMLPath =
Path.Combine(Package.Current.InstalledLocation.Path, "XML/Customers.xml");
XDocument xmlDoc = XDocument.Load(customerXMLPath);
var updateQuery = from r in xmlDoc.Descendants("Customer")
where r.Element("CustomerId").Value == txtCustomerId.Text
select r;
foreach (var query in updateQuery)
{
query.Element("State").SetValue(txtState.Text);
}
xmlDoc.Save(customerXMLPath);
}
编辑:根据评论,在UWP中保存没有超载。那么这是否意味着(根据另一条评论)我必须保存为流?如果是这样的话我不会覆盖文件吗? < - 当我只是想改变一些价值时,这是没有意义的,但也许我误解了答案。
我的假设是有一种方法可以在UWP中更新XML文件,所以我只是这样做错了吗?推荐的方式是什么?顺便说一句,SQLite现在不是一个选项,因为文件必须保持XML格式
答案 0 :(得分:0)
不要在Path.Combine
语句中使用自己的“斜杠”标记,而是让它为您完成。因此,您知道您所使用的操作系统可以接受您的路径。
切换它:
string customerXMLPath =
Path.Combine(Package.Current.InstalledLocation.Path, "XML/Customers.xml");
对此:
string customerXMLPath =
Path.Combine(Package.Current.InstalledLocation.Path, "XML", "Customers.xml");
但这不一定是你的问题。您似乎正在尝试写入READ ONLY位置。 See this post for more。我会在这里引用答案的文字部分。
...问题是我们无法更新安装文件夹的文件内容,这个文件夹只读一个,所以解决方法是将你的xml文件放在我们有读写权限的文件夹中...
答案 1 :(得分:0)
我想我可能已经为此找到了解决方案,但它涉及覆盖文件。它可能很脏,但它对我有用。
我在ApplicationData.Current.LocalFolder.Path
位置创建了一个xml文件。在安装目录(Package.Current.InstalledLocation.Path)
中工作可能很困难,因为其中的所有文件都是沙盒,您将无权修改它们。
所以第一部分看起来像这样。
string customerXMLPath =
Path.Combine(ApplicationData.Current.LocalFolder.Path, "XML/Customers.xml");
之后,您可以运行XDocument
代码。但是不要打扰调用xmlDoc.Save(customerXMLPath)
,因为这在UWP应用程序中不起作用。
所以第二部分看起来像这样。就像你已经一样。
XDocument xmlDoc = XDocument.Load(customerXMLPath);
var updateQuery = from r in xmlDoc.Descendants("Customer")
where r.Element("CustomerId").Value == txtCustomerId.Text
select r;
foreach (var query in updateQuery)
{
query.Element("State").SetValue(txtState.Text);
}
最后一部分是您必须将XDocument
的内容保存到文件中,从而覆盖文件中已有的任何内容。由于这是await
操作,因此建议您也使用方法async
。 StorageFolder
和StorageFile
应该用于获取位置和文件娱乐。
所以最后一部分看起来像这样。
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
var newfile = await storageFolder.CreateFileAsync("Customers.xml",
CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(newfile, xmlDoc.ToString());
因此完整的示例将如下所示。
using System.Xml.Linq;
using Windows.Storage;
using System.IO;
using System.Linq;
private void cmdStart_Click(object sender, RoutedEventArgs e)
{
SaveXml();
}
private async void SaveXml()
{
string XML_DATA_FILE = "Customer.xml";
string customerXMLPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, XML_DATA_FILE);
if (File.Exists(xmlPath))
{
XDocument xmlDoc = XDocument.Load(customerXMLPath);
var updateQuery = from r in xmlDoc.Descendants("Customer")
where r.Element("CustomerId").Value == txtCustomerId.Text
select r;
foreach (var query in updateQuery)
{
query.Element("State").SetValue(txtState.Text);
}
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
var newfile = await storageFolder.CreateFileAsync(XML_DATA_FILE,
CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(newfile, xmlDoc.ToString());
}
}
我希望这会有所帮助并提供一些指导。
干杯。