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

XML反序列化存储类型时触发异常问题求助

问题描述

反序列化其他开发者提供的XML到C#类时,持续抛出InvalidOperationException异常,提示“未识别指定类型:name='string', namespace='http://www.w3.org/2001/XMLSchema'”,异常触发于DevListViewItem类的Tag属性处。若将Tag设为string类型,可正常读取文本,但无法保留类型信息用于后续序列化。

XML示例
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfDevListViewItem xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <DevListViewItem>
    <Index>0</Index>
    <Key>0</Key>
    <Tag xsi:type="xsd:string">[Category] = 0 And [CanOpen] = False</Tag>
    <Group />
    <Text>Can Open?</Text>
    <Subitem1>[Category] = 0 And [CanOpen] = False</Subitem1>
    <Subitem1Integer>0</Subitem1Integer>
    <Subitem2Integer>0</Subitem2Integer>
    <Subitem3Integer>0</Subitem3Integer>
    <ExtraData />
    <IsRead>true</IsRead>
    <Iconindex>0</Iconindex>
    <Sort />
    <Condition>false</Condition>
    <Checked>false</Checked>
    <HasInfoButton>false</HasInfoButton>
    <HasExecuteButton>false</HasExecuteButton>
    <IsBold>false</IsBold>
  </DevListViewItem>
</ArrayOfDevListViewItem>
现有C#代码
public class FilterXMLSchema
{
    public class Tag
    {
        [XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
        public string Type { get; set; }

        [XmlText]
        public string Text { get; set; }
    }

    public class DevListViewItem
    {
        [XmlElement(ElementName = "Index")]
        public int Index { get; set; }

        [XmlElement(ElementName = "Key")]
        public string Key { get; set; }

        [XmlElement(ElementName = "Tag")]
        public Tag Tag { get; set; }

        [XmlElement(ElementName = "Group")]
        public object Group { get; set; }

        [XmlElement(ElementName = "Text")]
        public string Text { get; set; }

        [XmlElement(ElementName = "Subitem1")]
        public string Subitem1 { get; set; }

        [XmlElement(ElementName = "Subitem1Integer")]
        public int Subitem1Integer { get; set; }

        [XmlElement(ElementName = "Subitem2Integer")]
        public int Subitem2Integer { get; set; }

        [XmlElement(ElementName = "Subitem3Integer")]
        public int Subitem3Integer { get; set; }

        [XmlElement(ElementName = "ExtraData")]
        public object ExtraData { get; set; }

        [XmlElement(ElementName = "IsRead")]
        public bool IsRead { get; set; }

        [XmlElement(ElementName = "Iconindex")]
        public int Iconindex { get; set; }

        [XmlElement(ElementName = "Sort")]
        public object Sort { get; set; }

        [XmlElement(ElementName = "Condition")]
        public bool Condition { get; set; }

        [XmlElement(ElementName = "Checked")]
        public bool Checked { get; set; }

        [XmlElement(ElementName = "HasInfoButton")]
        public bool HasInfoButton { get; set; }

        [XmlElement(ElementName = "HasExecuteButton")]
        public bool HasExecuteButton { get; set; }

        [XmlElement(ElementName = "IsBold")]
        public bool IsBold { get; set; }

        public override string ToString()
        {
            return string.Format("{0}", Text);
        }
    }

    public class ArrayOfDevListViewItem
    {
        [XmlElement(ElementName = "DevListViewItem", Namespace = "")]
        public List<DevListViewItem> DevListViewItem = new();

        [XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2001/XMLSchema")]
        public string Xsi;

        [XmlAttribute(AttributeName = "xsd", Namespace = "http://www.w3.org/2001/XMLSchema")]
        public string Xsd;

        [XmlText]
        public string Text;
    }
}
解决方案

问题核心是XML中的xsi:type="xsd:string"标记未被正确处理:序列化器试图将其解析为自定义类型,但你的Tag类定义与该逻辑不匹配。以下是两种可行解决方式:

方法一:用object类型+注册已知类型

将Tag改为object类型,并通过XmlInclude注册可能的类型(比如string),让序列化器自动识别并保留xsi:type信息:

public class FilterXMLSchema
{
    [XmlInclude(typeof(string))]
    public class DevListViewItem
    {
        // 其他属性保持不变
        [XmlElement(ElementName = "Tag")]
        public object Tag { get; set; }
        // 其他属性保持不变
    }

    // 其他类保持不变
}

反序列化后Tag会自动转为string类型,后续序列化时也能正确输出xsi:type标记。

方法二:自定义Tag类并跳过类型解析

如果要保留自定义Tag类,需手动处理xsi:type属性,避免序列化器将其当作类型标记:

// 保持Tag类定义不变
public class Tag
{
    [XmlAttribute("type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
    public string Type { get; set; }

    [XmlText]
    public string Text { get; set; }
}

创建序列化器时,通过XmlAttributeOverrides告诉序列化器不要解析Tag的xsi:type:

var overrides = new XmlAttributeOverrides();
var attrs = new XmlAttributes();
attrs.XmlElements.Add(new XmlElementAttribute("Tag"));
overrides.Add(typeof(DevListViewItem), "Tag", attrs);

var serializer = new XmlSerializer(typeof(ArrayOfDevListViewItem), overrides);
// 执行反序列化操作

此方式会将xsi:type的值存入Tag.Type,文本存入Tag.Text,完全保留原类型信息。

额外优化:修正命名空间声明处理

原代码中ArrayOfDevListViewItem的Xsi和Xsd属性定义错误,XML中的xmlns:xsi/xsd是命名空间声明,需用XmlNamespaceDeclarations处理:

public class ArrayOfDevListViewItem
{
    [XmlElement(ElementName = "DevListViewItem")]
    public List<DevListViewItem> DevListViewItem = new();

    [XmlNamespaceDeclarations]
    public XmlSerializerNamespaces Namespaces = new XmlSerializerNamespaces();
}

初始化时添加命名空间:

var array = new ArrayOfDevListViewItem();
array.Namespaces.Add("xsd", "http://www.w3.org/2001/XMLSchema");
array.Namespaces.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");

内容的提问来源于Stack Exchange,提问作者Gazz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 04:37:15