#c# #nuget #xml-serialization
#c# #nuget #xml-сериализация
Вопрос:
Я пытаюсь десериализовать NuGet NuSpec. У меня все это работало, и я попытался добавить поддержку элемента репозитория (метаданных). По какой-то причине он не заполняет элемент репозитория, и я не могу понять, почему. Я создал отдельный файл cs, который должен продемонстрировать проблему. Кто-нибудь может сказать, что я сделал не так, что он не десериализует элемент репозитория?
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, null, new XmlRootAttribute("package"),
"http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd"),
new XmlSerializer(typeof(Package), null, null, new XmlRootAttribute("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; }
}
}
}
Ответ №1:
Элемент репозитория определяется атрибутами, поэтому вместо него следует использовать XmlAttribute . Тем не менее, я настоятельно рекомендую вам изучить возможность автоматической генерации классов из nuspec XSD (найдите, как «генерировать классы C # из XSD»). Когда у вас настолько четко определенная структура XML, вам следует избегать создания собственных классов
Комментарии:
1. >> автоматическая генерация классов из nuspec XSD<< Я отключил этот код для публикации. Изначально я использовал XSD, он сгенерировал атрибут Namespace=»{0}». У меня возникли проблемы с пространствами имен, поскольку файл NuSpec имеет разные версии. Итак, я сократил весь этот код и сохранил только изначально важные элементы. Я не знаю, что такое пространство имен =»{0}», и я не смог найти никакой документации по нему. Это XSD: github.com/NuGet/NuGet . Client/blob/dev/src/NuGet.Core/…
2. @TimBassett Я раньше не делал этого с помощью nuspec XSD, но я считаю, что вам просто нужно ввести пространство имен для используемой вами версии схемы