2016-07-08 79 views
0

我想保存一些变化回到一个XML文件使用Linq,我已经看到很多例如SO和教程网站这样做,但出于某种原因,我在xmlDoc.Save(customerXMLPath)上出现错误; line 参数1:无法从'字符串'转换为'System.IO.Stream'我的XDocument保存有什么问题?

我看过的大部分示例都是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格式

+1

[保存和XDocument到“使用流”中的文件可能的重复](http://stackoverflow.com/questions/35090648/save-and-xdocument-to-a-file-in-a-using -stream) – BrunoLM

+0

这个问题并不完全相同,但我认为这里的答案也适用于此 – BrunoLM

+0

根据文档,在UWP中“保存”超载不可用。 –

回答

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

但不一定是你的问题。看起来您正尝试写入只读位置。 See this post for more。我将在此引用答案的文本部分。

...问题是我们无法更新安装文件夹的文件内容,该文件夹是只读文件夹,所以解决方法是将您的xml文件放在我们拥有读写权限的文件夹中...

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。应该使用StorageFolderStorageFile来获取位置和文件重新创建。

所以最后一部分看起来像这样。

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

我希望这有助于并提供一些指导。

干杯。

+0

您的解决方案看起来很有希望。我正在使用的XML文件现在是一个静态文件,但它的想法是在一天开始时更新。目前我刚刚在应用程序根目录的一个文件夹中抛出了一个文件,但是现在我意识到我稍后会导入一个问题。所以我正在重新思考这个部分。只要应用程序已安装,Current.LocalFolder.Path是否保留在客户端上?如果是这样,我可以计划将其导入那里并使用该目录中的文件进行处理,因为覆盖文件在这种情况下不是问题 –