【问题标题】:What is wrong with my XDocument save?我的 XDocument 保存有什么问题?
【发布时间】:2016-07-08 01:41:00
【问题描述】:

我正在尝试使用 Linq 将一些更改保存回 XML 文件,我在 SO 和教程网站上看到了很多这样的示例,但由于某种原因,我在 xmlDoc.Save(customerXMLPath); 上遇到错误。 参数 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);
}

编辑:根据 cmets,UWP 中的 Save 没有过载。那么这是否意味着(基于另一条评论)我必须保存为流?如果是这种情况,我是否不必覆盖文件?

我的假设是有一种方法可以在 UWP 中更新 XML 文件,所以我只是把这一切都搞错了吗?推荐的方法是什么?顺便说一句,SQLite 现在不是一个选项,因为文件必须保持 XML 格式

【问题讨论】:

  • 问题不太一样,但我认为答案也适用于这里
  • 根据文档,Save 的重载在 UWP 中不可用。
  • 好吧,其他人偶然发现了这个线程并且没有意识到它(因为我一开始没有得到它)​​。代码“没有问题”(不完全正确,但是......)。问题是 UWP 根本不允许保存(至少在我尝试过的任何文件夹中都不允许)。但是,@Technaur 建议的解决方案可能适用于我的情况。

标签: c# xml linq uwp


【解决方案1】:

不要在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文件放在我们拥有读写权限的文件夹中...

【讨论】:

    【解决方案2】:

    我想我可能已经找到了解决方案,但它涉及覆盖文件。它可能很脏,但对我有用。

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

    我希望这会有所帮助并提供一些指导。

    干杯。

    【讨论】:

    • 您的解决方案看起来很有希望。我正在使用的 XML 文件现在是一个静态文件,但想法是让它在一天开始时得到更新。目前,我刚刚在应用程序根目录的文件夹中添加了一个文件,但我现在意识到稍后导入该文件时会遇到问题。所以我正在重新考虑那部分。只要安装了应用程序,Current.LocalFolder.Path 是否会保留在客户端上?如果是这样,我可以计划在那里导入它并使用该目录中的文件,因为在这种情况下覆盖文件并不是真正的问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-06
    • 2012-09-10
    相关资源
    最近更新 更多