2016-07-08 63 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是否保留在客戶端上?如果是這樣,我可以計劃將其導入那裏並使用該目錄中的文件進行處理,因爲覆蓋文件在這種情況下不是問題 –