XmlSerializer缺少元素

问题描述

我正在尝试反序列化NuGet NuSpec。我已经完成所有工作,并尝试添加对(元数据的)存储库元素的支持。由于某种原因,它不会填充Repository元素,我也无法弄清原因。我编写了一个独立的cs文件,该文件应演示该问题。谁能告诉我我做错了什么,它不会反序列化Repository元素?

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using FluentAssertions;
using Xunit;

namespace PipelineFunctions.Tests.Build.Nuget
{
    public class SingleFilePackageTestForStackOverflow
    {

        [Fact]
        public void Fromtest()
        {
            var xml = @"<?xml version=""1.0"" encoding=""utf-8""?>
<package xmlns=""http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd"">
  <Metadata>
    <id>YadaYada.Amazon.Data.Test</id>
    <version>20.271.10</version>
    <authors>Amazon.Data.Test</authors>
    <owners>Amazon.Data.Test</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Package Description</description>
    <repository type=""git"" url=""https://git-codecommit.us-east-1.amazonaws.com/v1/repos/zzzzz"" branch=""fast06"" commit=""51d5ea8ec9aefcd8a6d6c8a4c37a3fffe7c8d12f"" />
    <dependencies>
      <group targetFramework="".NETCoreApp3.1"">
        <dependency id=""YadaYada.Amazon.Data"" version=""20.271.10"" exclude=""Build,Analyzers"" />
        <dependency id=""YadaYada.Amazon.Entity.Test"" version=""20.271.10"" exclude=""Build,Analyzers"" />
        <dependency id=""FluentAssertions"" version=""5.10.3"" exclude=""Build,Analyzers"" />
        <dependency id=""Microsoft.NET.Test.Sdk"" version=""16.7.1"" exclude=""Build,Analyzers"" />
        <dependency id=""YadaYada.Autoparts.Entity.Test"" version=""20.265.6"" exclude=""Build,Analyzers"" />
        <dependency id=""YadaYada.Data.Library.Test"" version=""20.271.29"" exclude=""Build,Analyzers"" />
        <dependency id=""coverlet.collector"" version=""1.3.0"" exclude=""Build,Analyzers"" />
        <dependency id=""xunit"" version=""2.4.1"" exclude=""Build,Analyzers"" />
        <dependency id=""xunit.runner.visualstudio"" version=""2.4.3"" exclude=""Build,Analyzers"" />
      </group>
    </dependencies>
  </Metadata>
</package>";

            var p = Package.From(xml);
            // this passes
            p.Metadata.Id.Should().Be("YadaYada.Amazon.Data.Test");
            // this fails
            p.Metadata.Repository.Url.Should().NotBeNullOrEmpty();
        }
        [XmlRoot(ElementName = "package")]
        public class Package
        {
            [XmlElement(ElementName = "Metadata")]
            public Metadata Metadata { get; set; } = new Metadata();

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


            public static Package From(string text)
            {
                var serializers = new[]
                {
                new XmlSerializer(typeof(Package),null,new XmlRootAttribute("package"),"http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd"),new XmlSerializer(typeof(Package),"http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd")};

                using var reader = new XmlTextReader(new StringReader(text));

                foreach (var xmlSerializer in serializers)
                {
                    

                    if (xmlSerializer.CanDeserialize(reader))
                    {
                        var deserialize = xmlSerializer.Deserialize( reader) as Package;
                        return deserialize;
                    }
                }


                throw new NotSupportedException($"Cannot deserialize {text}");
            }

        }
        [XmlRoot(ElementName = "Metadata")]
        public class Metadata
        {
            [XmlElement(ElementName = "id")]
            public string Id { get; set; }
            [XmlElement(ElementName = "version")]
            public string Version { get; set; }
            [XmlElement(ElementName = "authors")]
            public string Authors { get; set; }
            [XmlElement(ElementName = "owners")]
            public string Owners { get; set; }
            [XmlElement(ElementName = "requireLicenseAcceptance")]
            public string RequireLicenseAcceptance { get; set; }
            [XmlElement(ElementName = "description")]
            public string Description { get; set; }

            [XmlElement(ElementName = "dependencies")]
            public Dependencies Dependencies { get; set; } = new Dependencies();

            [XmlElement(ElementName = "repository")]
            public Repository Repository { get; set; } = new Repository();
        }

        [XmlRoot(ElementName = "repository")]
        public class Repository
        {
            [XmlElement(ElementName = "type")]
            public string Type { get; set; }

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

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

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

        [XmlRoot(ElementName = "dependencies")]
        public class Dependencies
        {
            [XmlElement(ElementName = "group")]
            public Group Group { get; set; } = new Group();
        }

        [XmlRoot(ElementName = "group")]
        public class Group
        {
            [XmlElement(ElementName = "dependency")]
            public List<Dependency> Dependency { get; set; } = new List<Dependency>();
            [XmlAttribute(AttributeName = "targetFramework")]
            public string TargetFramework { get; set; }
        }
        [XmlRoot(ElementName = "dependency")]
        public class Dependency
        {
            [XmlAttribute(AttributeName = "id")]
            public string Id { get; set; }
            [XmlAttribute(AttributeName = "version")]
            public string Version { get; set; }
            [XmlAttribute(AttributeName = "exclude")]
            public string Exclude { get; set; }
        }
    }
}

解决方法

repository元素由属性定义,因此应改为使用XmlAttribute。但是,我高度建议您研究从nuspec XSD自动生成类(搜索如何“从XSD生成C#类”)。当您具有定义良好的XML结构时,应避免创建自己的类