简体   繁体   English

XDocument保存有什么问题?

[英]What is wrong with my XDocument save?

I am trying to save some changes back to an XML file using Linq and I have seen many examples on SO and tutorial sites doing it like this but for some reason I am getting an error on the xmlDoc.Save(customerXMLPath); 我正在尝试使用Linq将一些更改保存回XML文件,并且在SO和教程网站上看到了许多像这样的示例,但是由于某种原因,我在xmlDoc.Save(customerXMLPath)上遇到了错误。 line Argument 1: cannot convert from 'string' to 'System.IO.Stream' . line Argument 1:无法从'string'转换为'System.IO.Stream'

Most of the samples I have seen are ASP.Net samples but I wouldn't think that should make much a difference on the syntax (this is a UWP app). 我见过的大多数示例都是ASP.Net示例,但我认为这不会在语法上有太大区别(这是UWP应用)。 Can someone please tell me what I am doing wrong? 有人可以告诉我我做错了吗?

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);
}

Edit: according to the comments there is no overload for Save in UWP. 编辑:根据注释,UWP中的保存没有重载。 So does that mean (based on another comment) that I have to save as a stream? 那么这是否意味着(基于另一条评论)我必须另存为流? If that is the case wouldn't I have to overwrite the file? 如果是这种情况,我是否不必覆盖文件? <-- that doesn't make sense when I am just trying to change a few values but maybe I misunderstood the answer. <-当我仅尝试更改一些值时没有任何意义,但是也许我误解了答案。

My assumption is that there is a way to update a XML file in UWP so am I just going about this all wrong? 我的假设是,有一种方法可以在UWP中更新XML文件,所以我是否会出错? What is the recommended way? 推荐的方法是什么? By the way SQLite is not an option right now because the files have to remain in XML format 顺便说一句,SQLite现在不是选项,因为文件必须保持XML格式

Instead of using your own "slash" mark in the Path.Combine statement, let it do that for you. 不要在Path.Combine语句中使用您自己的“斜杠”标记, Path.Combine让它为您完成。 So you know your path is acceptable to the operating system you are using. 因此,您知道所使用的操作系统可接受您的路径。

Switch this: 切换此:

string customerXMLPath = 
        Path.Combine(Package.Current.InstalledLocation.Path, "XML/Customers.xml");

To this: 对此:

string customerXMLPath = 
        Path.Combine(Package.Current.InstalledLocation.Path, "XML", "Customers.xml");

But that isn't necessarily your problem. 但这不一定是您的问题。 It appears you are trying to write to a READ ONLY location. 看来您正在尝试写入只读位置。 See this post for more . 有关更多信息,请参见此帖子 I'll quote the text portion of the answer here. 我将在此处引用答案的文本部分。

...the problem is we cannot update file content of the installation folder, this folder a read-only one, so the workaround is to place your xml file in the folder which we have both read and write rights... ...问题是我们无法更新安装文件夹的文件内容,该文件夹是只读文件夹,因此解决方法是将xml文件放在我们拥有读写权限的文件夹中...

I think I might have found a solution for this, but it involves overriding files. 我想我可能已经找到了解决方案,但这涉及覆盖文件。 It might be dirty, but it works for me. 它可能很脏,但对我有用。

I created a xml file in the ApplicationData.Current.LocalFolder.Path location. 我在ApplicationData.Current.LocalFolder.Path位置中创建了一个xml文件。 Working in the install directory (Package.Current.InstalledLocation.Path) can be difficult since all the files in there are sand-boxed, you will not have permissions to modify them. 在安装目录(Package.Current.InstalledLocation.Path)可能很困难,因为其中的所有文件都被沙盒化,您将无权修改它们。

So the first section will look something like this. 因此,第一部分将如下所示。

string customerXMLPath = 
Path.Combine(ApplicationData.Current.LocalFolder.Path, "XML/Customers.xml");

After that you can run your XDocument code. 之后,您可以运行XDocument代码。 But don't bother calling xmlDoc.Save(customerXMLPath) because that won't work in a UWP app. 但是不要打扰xmlDoc.Save(customerXMLPath)因为这在UWP应用程序中不起作用。

So the second section will look something like this. 所以第二部分看起来像这样。 Like you have already. 就像你已经。

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);
}

The last part is where you would have to save the contents of your XDocument to the file, overriding any content already in the file. 最后一部分是您必须将XDocument的内容保存到文件中,从而覆盖文件中已有的所有内容。 Since this is an await operation, it would be advised that you make your method async as well. 由于这是一个await操作,因此建议您也使方法async StorageFolder and StorageFile should be used to get the location and file recreation. 应该使用StorageFolderStorageFile来获取位置和文件重新创建。

So the last part would look something like this. 所以最后一部分看起来像这样。

StorageFolder storageFolder = ApplicationData.Current.LocalFolder;                
var newfile = await storageFolder.CreateFileAsync("Customers.xml",
CreationCollisionOption.ReplaceExisting);

await FileIO.WriteTextAsync(newfile, xmlDoc.ToString());

So the full example will look like this. 因此,完整的示例将如下所示。

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());                
    }            
}

I hope this helps and gives some guidance. 我希望这会有所帮助并提供一些指导。

Cheers. 干杯。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM