XDocument Saving Error in Mono”;此XmlWriter不接受处于Prolog状态的Text
本文关键字:不接受 Prolog 状态 Text XmlWriter Error Saving in Mono XDocument | 更新日期: 2023-09-27 18:22:20
我正在尝试保存一个xml文档,我一直在尝试让我的代码工作,但mono抛出了一个非常奇怪的错误。我已将它试图保存的文件授予完全所有权。
一个例子是group.test.test到"Hello world!"
这是代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Linq;
namespace Classic6
{
public class XmlSettings
{
private Dictionary<string, XmlSetting> Values { get; set; }
private string[] SettingFiles;
public bool EnableSaving { get; set; }
public event EventHandler<SettingChangedEventArgs> OnSettingChanged;
/// <summary>
/// The location of the XML file that new keys
/// should be stored in (when a key is added
/// via XmlSettings["key"] without a file, it
/// will be saved here.
/// </summary>
public static string DefaultFile { get; set; }
public XmlSettings()
{
Values = new Dictionary<string, XmlSetting>();
EnableSaving = false;
}
public void Load(string SettingsDirectory)
{
SettingFiles = Directory.GetFiles(SettingsDirectory, "*.xml", SearchOption.AllDirectories);
foreach (string file in SettingFiles)
{
try
{
Stream s = File.Open(file, FileMode.Open);
XDocument d = XDocument.Load(s);
s.Close();
LoadRecursive(d.Root, file, string.Empty);
}
catch { }
}
if (string.IsNullOrEmpty(DefaultFile))
DefaultFile = Path.Combine(SettingsDirectory, "bla.xml.bak.invalid");
}
private void LoadRecursive(XElement root, string sourceFile, string path)
{
foreach (XElement e in root.Elements())
{
if (e.Elements().Count() != 0)
LoadRecursive(e, sourceFile, path + e.Name + ".");
foreach (XAttribute a in e.Attributes())
{
Values[(path + e.Name.LocalName.ToString() + "." +
a.Name.LocalName.ToString()).ToLower()] = new XmlSetting(sourceFile, a.Value, true);
}
if (Values.ContainsKey((path + e.Name.LocalName.ToString()).ToLower()))
{
if (Values[(path + e.Name.LocalName.ToString()).ToLower()].Value != e.Value)
{
if (OnSettingChanged != null)
OnSettingChanged(this, new SettingChangedEventArgs((path + e.Name.LocalName.ToString()).ToLower(),
Values[(path + e.Name.LocalName.ToString()).ToLower()].Value, e.Value));
}
}
Values[(path + e.Name.LocalName.ToString()).ToLower()] = new XmlSetting(sourceFile, e.Value, false);
}
}
public int GetInt(string Key)
{
int i = -1;
if (!int.TryParse(this[Key], out i) && !Key.StartsWith("command") && !Key.Contains("port"))
Server.server.Log("Setting error: " + Key + " is not a valid integer.");
return i;
}
public bool GetBool(string Key)
{
bool b = false;
if (!bool.TryParse(this[Key], out b))
Server.server.Log("Setting error: " + Key + " is not a valid boolean.");
return b;
}
public bool ContainsKey(string Key)
{
return Values.ContainsKey(Key.ToLower());
}
public string this[string key]
{
get
{
if (!Values.ContainsKey(key.ToLower()))
return "";
return Values[key.ToLower()].Value;
}
set
{
if (OnSettingChanged != null)
OnSettingChanged(this, new SettingChangedEventArgs(key, Values.ContainsKey(key.ToLower()) ? Values[key.ToLower()].Value : DefaultFile, value));
if (Values.ContainsKey(key))
Values[key.ToLower()].Value = value;
else
Values[key.ToLower()] = new XmlSetting(DefaultFile, value, false);
if (string.IsNullOrEmpty(DefaultFile))
return;
if (!EnableSaving)
return;
XDocument d = new XDocument();
if (File.Exists(Values[key.ToLower()].SourceFile))
{
Stream s = File.Open(Values[key.ToLower()].SourceFile, FileMode.OpenOrCreate);
d = XDocument.Load(s, LoadOptions.PreserveWhitespace);
s.Close();
}
else
{
d = new XDocument();
d.Add(new XElement("Classic6"));
}
// Locate this property
string[] parts = key.ToLower().Split('.');
XElement currentElement = d.Root;
for (int i = 0; i < parts.Length; i++ )
{
bool found = false;
if (parts.Length - 1 == i)
{
foreach (XAttribute a in currentElement.Attributes())
{
if (a.Name.LocalName.ToLower() == parts[i])
{
found = true;
break;
}
}
}
foreach (XElement e in currentElement.Elements())
{
if (e.Name.LocalName.ToLower() == parts[i])
{
currentElement = e;
found = true;
break;
}
}
if (!found)
{
XElement el = new XElement(parts[i]);
currentElement.Add(el);
currentElement = el;
}
}
if (Values[key.ToLower()].IsAttribute)
currentElement.SetAttributeValue(parts[parts.Length - 1], Values[key.ToLower()].Value);
else
currentElement.SetValue(Values[key.ToLower()].Value);
d.Save(Values[key.ToLower()].SourceFile);
}
}
}
internal class XmlSetting
{
public string SourceFile { get; set; }
public string Value { get; set; }
public bool IsAttribute { get; set; }
public XmlSetting(string SourceFile, string Value, bool IsAttribute)
{
this.SourceFile = SourceFile;
this.Value = Value;
this.IsAttribute = IsAttribute;
}
}
public class SettingChangedEventArgs : EventArgs
{
public string Key { get; set; }
public string OldValue { get; set; }
public string NewValue { get; set; }
public SettingChangedEventArgs(string Key, string OldValue, string NewValue)
{
this.Key = Key;
this.OldValue = OldValue;
this.NewValue = NewValue;
}
}
}
这是它给我的错误:
Unhandled Exception: System.InvalidOperationException: This XmlWriter does not accept Text at this state Prolog.
at System.Xml.XmlTextWriter.ShiftStateContent (System.String occured, Boolean allowAttribute) [0x00000] in <filename unknown>:0
at System.Xml.XmlTextWriter.WriteString (System.String text) [0x00000] in <filename unknown>:0
at System.Xml.DefaultXmlWriter.WriteString (System.String text) [0x00000] in <filename unknown>:0
at System.Xml.Linq.XText.WriteTo (System.Xml.XmlWriter w) [0x00000] in <filename unknown>:0
at System.Xml.Linq.XDocument.WriteTo (System.Xml.XmlWriter w) [0x00000] in <filename unknown>:0
at System.Xml.Linq.XDocument.Save (System.Xml.XmlWriter w) [0x00000] in <filename unknown>:0
at System.Xml.Linq.XDocument.Save (System.String filename, SaveOptions options) [0x00000] in <filename unknown>:0
at System.Xml.Linq.XDocument.Save (System.String filename) [0x00000] in <filename unknown>:0
at Classic6.XmlSettings.set_Item (System.String key, System.String value) [0x00000] in <filename unknown>:0
at Classic6.CmdSettings.Use (Classic6.RemoteClient c, System.String message) [0x00000] in <filename unknown>:0
at Classic6.ClassicServer.HandleCommand (Classic6.RemoteClient c, System.String msg) [0x00000] in <filename unknown>:0
at Classic6Server.Program.ParseInput (System.String input) [0x00000] in <filename unknown>:0
at Classic6Server.Program.Main () [0x00000] in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidOperationException: This XmlWriter does not accept Text at this state Prolog.
at System.Xml.XmlTextWriter.ShiftStateContent (System.String occured, Boolean allowAttribute) [0x00000] in <filename unknown>:0
at System.Xml.XmlTextWriter.WriteString (System.String text) [0x00000] in <filename unknown>:0
at System.Xml.DefaultXmlWriter.WriteString (System.String text) [0x00000] in <filename unknown>:0
at System.Xml.Linq.XText.WriteTo (System.Xml.XmlWriter w) [0x00000] in <filename unknown>:0
at System.Xml.Linq.XDocument.WriteTo (System.Xml.XmlWriter w) [0x00000] in <filename unknown>:0
at System.Xml.Linq.XDocument.Save (System.Xml.XmlWriter w) [0x00000] in <filename unknown>:0
at System.Xml.Linq.XDocument.Save (System.String filename, SaveOptions options) [0x00000] in <filename unknown>:0
at System.Xml.Linq.XDocument.Save (System.String filename) [0x00000] in <filename unknown>:0
at Classic6.XmlSettings.set_Item (System.String key, System.String value) [0x00000] in <filename unknown>:0
at Classic6.CmdSettings.Use (Classic6.RemoteClient c, System.String message) [0x00000] in <filename unknown>:0
at Classic6.ClassicServer.HandleCommand (Classic6.RemoteClient c, System.String msg) [0x00000] in <filename unknown>:0
at Classic6Server.Program.ParseInput (System.String input) [0x00000] in <filename unknown>:0
at Classic6Server.Program.Main () [0x00000] in <filename unknown>:0
在xml文件中,它完全覆盖它,只留下以下内容:
<?xml version="1.0" encoding="utf-8"?>
与此有很大不同:
<?xml version="1.0" encoding="utf-8" ?>
<Classic6>
<group>
<test>Will I change</test>
<well>I hope so</well>
</group>
</Classic6>
我们发现:Mono显然不能很好地处理空白,所以这样做:
d = XDocument.Load(s, LoadOptions.None);
而不是这个
d = XDocument.Load(s, LoadOptions.PreserveWhitespace);
将使其正确保存。
你能检查你读取的文件的编码以及它是如何写的吗?可能是字节顺序标记让xmlwriter发疯了。
我在保留空白的同时找到了另一种解决方法。很明显,Mono无法保存使用LoadOptions.PreserveWhitespace打开的XDocument。这似乎是Mono运行时实现中的一个错误。因为,我在Windows平台上实现MS CLR时没有遇到任何问题。
解决方法如下:(在这里,您仍然可以在XDocument.Load方法中使用LoadOptions.PreserveWhitespace)
d.Root.Save(Values[key.ToLower()].SourceFile);
而不是使用
d.Save(Values[key.ToLower()].SourceFile);
在Ubuntu 11.10平台上使用MonoJIT编译器2.10.5版本对我来说效果很好。