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

反序列化Excel XML文件时属性无法正常反序列化的解决方法

Excel导出XML反序列化时Worksheet.Name属性为null的解决方法

问题场景

有一份从Excel导出的XML文件,核心结构如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
    xmlns:o="urn:schemas-microsoft-com:office:office"
    xmlns:x="urn:schemas-microsoft-com:office:excel"
    xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
    xmlns:html="http://www.w3.org/TR/REC-html40">
    ...
    <Worksheet ss:Name="Page1">
    ...
    </Worksheet>
</Workbook>

对应的C#序列化模型定义如下:

using System.Xml.Serialization;
using System.Collections.Generic;

[XmlRoot(ElementName = "Worksheet", Namespace = "urn:schemas-microsoft-com:office:spreadsheet")]
public class Worksheet
{
    [XmlAttribute(AttributeName = "Name", Namespace = "urn:schemas-microsoft-com:office:spreadsheet")]
    public string Name { get; set; }
}

[XmlRoot(ElementName = "Workbook", Namespace = "urn:schemas-microsoft-com:office:spreadsheet")]
public class Workbook
{
    [XmlElement(ElementName = "Worksheet", Namespace = "urn:schemas-microsoft-com:office:spreadsheet")]
    public List<Worksheet> Worksheet { get; set; }
}

尝试两种反序列化方式(使用XmlNamespaceManager或直接读取文件),均出现Worksheet.Name属性为null的情况。但修改XML和模型中ss命名空间的声明值后,属性可正常读取。需要在保留原命名空间的前提下解决该问题。

原因分析

问题源于XML中命名空间的冲突:根节点Workbook同时声明了默认命名空间xmlns="urn:schemas-microsoft-com:office:spreadsheet"和别名空间xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet",二者指向同一个命名空间。XmlSerializer处理时,带前缀的属性(如ss:Name)会被视为独立的命名空间限定属性,即使前缀对应的命名空间与默认一致,也需要明确匹配前缀的映射规则,否则无法正确绑定到模型属性。

解决方法

方案1:修改模型属性的XmlAttribute特性

直接调整Worksheet类中Name属性的特性,明确指定属性的前缀为ss,并设置Form为XmlSchemaForm.Qualified:

[XmlRoot(ElementName = "Worksheet", Namespace = "urn:schemas-microsoft-com:office:spreadsheet")]
public class Worksheet
{
    [XmlAttribute(AttributeName = "Name", 
                  Namespace = "urn:schemas-microsoft-com:office:spreadsheet",
                  Form = XmlSchemaForm.Qualified,
                  Prefix = "ss")]
    public string Name { get; set; }
}

修改后,使用原有的反序列化代码即可正常读取Name属性值。

方案2:使用XmlAttributeOverrides动态调整序列化规则

如果无法修改原模型类,可以在创建XmlSerializer时通过XmlAttributeOverrides动态覆盖属性的序列化配置:

// 创建属性覆盖配置
var overrides = new XmlAttributeOverrides();
var attrs = new XmlAttributes();
var nameAttr = new XmlAttributeAttribute
{
    AttributeName = "Name",
    Namespace = "urn:schemas-microsoft-com:office:spreadsheet",
    Form = XmlSchemaForm.Qualified,
    Prefix = "ss"
};
attrs.XmlAttribute = nameAttr;
overrides.Add(typeof(Worksheet), "Name", attrs);

// 使用覆盖配置创建序列化器
var serializer = new XmlSerializer(typeof(Workbook), overrides);

// 执行反序列化
using var fs = new FileStream("so.xml", FileMode.Open);
var wb = serializer.Deserialize(fs) as Workbook;
var ws = wb.Worksheet.First();
Console.WriteLine(ws.Name); // 输出:Page1

原理说明

当XML属性使用前缀标记时,XmlSerializer会严格匹配属性的前缀+命名空间组合。通过设置Form = XmlSchemaForm.Qualified,强制属性使用命名空间限定,并指定Prefix = "ss",即可让序列化器正确识别XML中的ss:Name属性,完成与模型属性的绑定。

内容的提问来源于stack exchange,提问作者S. Inf

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 02:44:57