C# XML 反序列化,其中节点属性不区分大小写,即使 xml 区分大小写

C# XML Deserialization where node attribute is case-insensitive even though xml is case sensitive

我正在尝试从 XML 文档中读取 PackageReferences。

我的 xml 文件如下所示:

<Project>
  <ItemGroup>
    <PackageReference Update="PackageName" Version="PackageVersion" />
  </ItemGroup>
</Project>

<Project>
  <ItemGroup>
    <PackageReference Update="PackageName" version="PackageVersion" />
  </ItemGroup>
</Project>

(第一个例子在“Version”中有一个大写的 V,第二个例子在“version”中有一个小写的 v)

我知道 XML 区分大小写。不幸的是,提交 xml 文件进行处理的客户经常会犯这种大小写错误。由于客户的数量和对这些类似文件的手动编辑,很难保持一致。我有哪些选项可以让我的 C# 程序安全地忽略大小写?目前我的程序只捕获 'Version' 中大写 V 的值,并为小写 'version' 示例放置 null。在这两种情况下,我仍然需要 PackageVersion 值。

这是我的代码:

Reader.cs:

var xmlResolver = new XmlSecureResolver(new XmlUrlResolver(), new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None));
using (var sr = new StringReader(this.FileSystem.File.ReadAllText(path)))
{
  var textReader = new XmlTextReader(sr) { Namespaces = false, XmlResolver = null };
  var serializer = new XmlSerializer(typeof(Project));
  return (Project)serializer.Deserialize(textReader);
}

Project.cs 部分 class:

{
    using System;
    using System.Xml.Serialization;

    [Serializable]
    public partial class Project
    {
        private ProjectItemGroup[] itemGroupField;

        [XmlElement("ItemGroup")]
        public ProjectItemGroup[] ItemGroup
        {
            //...
        }
    }

    [Serializable]
    public partial class ProjectItemGroup
    {
        private Package[] packageReferenceField;

        [XmlElement("PackageReference")]
        public Package[] PackageReference
        {
            get
            {
                return this.packageReferenceField;
            }
            set
            {
                this.packageReferenceField = value;
            }
        }
    }

}

Package.cs

    [Serializable]
    public class Package
    {
        [XmlAttribute(AttributeName = "Update")]
        public string Id { get; set; }

        [XmlAttribute(AttributeName = "Version")]
        public string Version { get; set; }
    }

我在这里查看了所有 properties 文档:https://docs.microsoft.com/en-us/dotnet/api/system.xml.xmltextreader.namespaces?view=net-6.0 and couldn't see a way to ignore case. (Earlier, I was able to ignore a namespace attribute on the root node as described here: )

我可能看到的选项是将整个文档小写并重新编写程序以期望所有小写值。另一种选择可能是也为版本添加一个小写字段,并以某种方式组合大写 Version 和小写 version 的结果。有没有我缺少的不那么骇人听闻的东西?

感谢@canton7 提供子类化 XmlTextReader 覆盖 LocalName 的想法。我最终对 Reader.cs 进行了以下更改:

public class CaseInsensitiveXmlTextReader : XmlTextReader
{
  public CaseInsensitiveXmlTextReader(System.IO.TextReader reader) : base(reader) { }
  public override string LocalName
  {
    get
    {
      if (String.Equals(base.LocalName, "version", StringComparison.Ordinal))
      {
        return "Version";
      }
      else
      {
        return base.LocalName;
      }
    }
  }
}

然后我更新了 textReader 以使用 CaseInsensitiveXmlTextReader:

var textReader = new CaseInsensitiveXmlTextReader(sr) { Namespaces = false, XmlResolver = xmlResolver };