You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# XmlDocument加载XML报意外XML声明错误问题咨询

问题根因

报错的直接原因是生成的XML文件存在多处XML声明,具体触发点有两个:

  • 首次写入公司信息时,StreamWriter使用了追加模式(构造函数第二个参数传了true),如果目标路径下已存在同名XML文件,序列化公司信息时会直接在旧文件末尾追加带XML声明的新内容,直接生成重复声明。
  • 追加机器数据的函数中,你配置的OmitXmlDeclaration = true没有生效。你直接将StreamWriter实例传给了序列化方法,没有通过XmlWriter加载你定义的写入配置,因此每次序列化机器数据时,都会自动输出完整的XML声明,每追加一台设备就多一个声明头。
  • 额外隐患:就算移除了多余声明,当前逐段拼接序列化片段的写法还会导致XML存在多个平级根节点,后续加载时依然会抛出格式错误。标准XML格式仅允许存在一个根节点。
临时修复方案(针对现有代码逻辑修改)

如果要保留当前逐段写入的逻辑,做两处修改即可解决重复声明问题:

  1. 修改保存按钮中首次写入公司信息的逻辑,创建新文件时使用覆盖模式,避免旧文件内容残留:
// 将StreamWriter构造函数的第二个参数从true改为false,首次写入采用覆盖模式
using (var writer = new StreamWriter(Path.Combine(appData, $"{txbCompany.Text}_{txbSiteName.Text}.xml"), false))
{
    x.Serialize(writer, companyProfile);
}
  1. 修改追加机器数据的函数,通过XmlWriter加载配置,让省略XML声明的设置真正生效,同时去掉多余的命名空间属性:
private void AppendMachineData(MachineProfile machineProfile, string fileName)
{
    System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(MachineProfile));
    var settings = new XmlWriterSettings();
    settings.Indent = true;
    settings.OmitXmlDeclaration = true;

    using (var streamWriter = new StreamWriter(fileName, true))
    // 用配置好的XmlWriter包裹流,写入规则才会生效
    using (var xmlWriter = XmlWriter.Create(streamWriter, settings))
    {
        // 清空默认命名空间,避免生成多余的xmlns属性
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add("", "");
        x.Serialize(xmlWriter, machineProfile, ns);
    }          
}

注意:该方案仅解决重复XML声明问题,依然存在多根节点的格式隐患,不推荐长期使用。

推荐实现方案(从根源避免格式问题)

不要采用逐段追加序列化片段的方式生成XML,这类写法非常容易生成不符合规范的XML文件。正确的做法是先组装完整的待存储数据对象,一次性完成序列化写入,全程只生成一个XML声明、一个根节点:

  1. 定义统一的存储根模型,包含公司信息和所有机器数据:
[Serializable]
public class ClientStoreModel
{
    public CompanyProfile CompanyInfo { get; set; }
    public List<MachineProfile> MachineList { get; set; }
}
  1. 保存时组装完整数据,一次性写入文件,完全不需要追加操作:
// 替换原来逐段序列化写入的逻辑
ClientStoreModel saveData = new ClientStoreModel();
saveData.CompanyInfo = companyProfile;
saveData.MachineList = dsMachineProfile.Cast<MachineProfile>().ToList();

System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(ClientStoreModel));
using (var writer = new StreamWriter(Path.Combine(appData, $"{txbCompany.Text}_{txbSiteName.Text}.xml"), false))
{
    serializer.Serialize(writer, saveData);
}
  1. 读取文件时直接反序列化为ClientStoreModel对象即可,不需要手动通过XmlDocument逐节点解析,代码更简洁,也不会出现XML格式解析错误。

内容的提问来源于stack exchange,提问作者ElectricRay81

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 18:25:25