2013-08-31 94 views
0

我有一種方法,它將XML加載到XDocument並修改其元素然後保存。 但是當我重新加載它。我得到這個錯誤:XDocument寫重複的XML

意外的XML聲明。 XML聲明必須是文檔中的第一個節點,並且不允許在它之前出現空白字符。

我檢查XML並看到XDocument沒有保存更改,但創建了一個副本並保存。

它保存舊的和新的一個這樣的示例XML:

<?xml version="1.0" encoding="UTF-8"?> 
<Ungdungs> 
    <Ungdung> 
    <Name>HERE City Lens</Name> 
    <Id>b0a0ac22-cf9e-45ba-8120-815450e2fd71</Id> 
    <Path>/Icon/herecitylens.png</Path> 
    <Version>Unknown</Version> 
    <Category>HERE</Category> 
    <Date>Uknown</Date> 
    </Ungdung> 
<?xml version="1.0" encoding="UTF-8"?> 
<Ungdungs> 
    <Ungdung> 
    <Name>HERE City Lens</Name> 
    <Id>b0a0ac22-cf9e-45ba-8120-815450e2fd71</Id> 
    <Path>/Icon/herecitylens.png</Path> 
    <Version>1.0.0.0</Version> 
    <Category>HERE</Category> 
    <Date>Uknown</Date> 
    </Ungdung> 

在這裏,我用來修改和保存XML代碼:

using (Stream stream = storage.OpenFile("APPSDATA.xml", FileMode.Open, FileAccess.ReadWrite)) 
       { 
        //var xdoc = XDocument.Load("APPSDATA.xml"); 
        var xdoc = XDocument.Load(stream, LoadOptions.None); 
        var listapp = from c in xdoc.Descendants("Ungdung") select c; 

        foreach (XElement app in listapp) 
        { 
         var xElement = app.Element("Name"); 
         if (xElement != null) 
          progressIndicator.Text = "Checking " + xElement.Value + "..."; 
         var element = app.Element("Id"); 
         if (element != null) 
         { 
          var appId = element.Value; 
          var appVersion = await GetAppsVersion(appId); 
          app.Element("Version").Value = appVersion.ToString(); 
         } 
        } 

        xdoc.Save(stream); 
       } 

我怎樣才能解決這個問題?

+0

在'xDoc.Save(stream);'之前嘗試'stream.SetLength(0);'。 – Vladimir

回答

3

看起來像在當前文件內容的末尾附加了修改過的文檔。這就是爲什麼你以後不能再解析它的原因。

我會分裂閱讀部分成不同的using聲明:

XDocument xdoc; 

using (Stream stream = storage.OpenFile("APPSDATA.xml", FileMode.Open, FileAccess.Read)) 
{ 
    xdoc = XDocument.Load(stream, LoadOptions.None); 
} 

var listapp = from c in xdoc.Descendants("Ungdung") select c; 

foreach (XElement app in listapp) 
{ 
    var xElement = app.Element("Name"); 
    if (xElement != null) 
     progressIndicator.Text = "Checking " + xElement.Value + "..."; 
    var element = app.Element("Id"); 
    if (element != null) 
    { 
     var appId = element.Value; 
     var appVersion = await GetAppsVersion(appId); 
     app.Element("Version").Value = appVersion.ToString(); 
    } 
} 

using (Stream stream = storage.OpenFile("APPSDATA.xml", FileMode.Truncate, FileAccess.Write)) 
{ 
    xdoc.Save(stream); 
} 

在第二using語句設置FileMode.Truncate將清除以前的文件內容,應該怎樣解決您的問題。

+1

或者直接將文件名直接傳遞給xdoc.Load/Save,它會生成所需的行爲。 – dtb

+0

@dtb當文件位於隔離存儲中時(在這裏看起來就是這種情況),它在Windows Phone中不起作用。 – MarcinJuraszek

+0

哇,它工作完美,太多了,我花了3個小時這樣:) –