Skip to content

Commit

Permalink
Support any namespace in NuspecReader (#278)
Browse files Browse the repository at this point in the history
The NuspecReader was hardcoded to always assume the nuspec v6 schema.
However, the NuGet client will use the _oldest_ schema it can when
creating a package.

Update the reader so it uses whatever the provided XML schema is.
  • Loading branch information
MattKotsenas authored Mar 15, 2024
1 parent 1741100 commit db652a8
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,29 @@ public void LicenseExpressionIsNullForFileLicenses()
nuspec.LicenseVersion.ShouldBeNull();
nuspec.LicenseUrl.ShouldBeNull();
}

// List of namespaces from https://github.com/NuGet/NuGet.Client/blob/6917e6c883d45f45672e20d4b1c45758dad2fa84/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/ManifestSchemaUtility.cs#L23-L50
[Theory]
[InlineData("http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd")]
[InlineData("http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd")]
[InlineData("http://schemas.microsoft.com/packaging/2011/10/nuspec.xsd")]
[InlineData("http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd")]
[InlineData("http://schemas.microsoft.com/packaging/2013/01/nuspec.xsd")]
[InlineData("http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd")]
public void ReaderCanParseKnownXmlNamespaces(string xmlns)
{
string contents =
$@"<package xmlns=""{xmlns}"">
<metadata>
<id>PackageL</id>
<version>16.4.60</version>
</metadata>
</package>";

NuspecReader nuspec = new NuspecReader(contents);

nuspec.Id.ShouldBe("PackageL");
nuspec.Version.ShouldBe("16.4.60");
}
}
}
22 changes: 18 additions & 4 deletions src/Microsoft.Build.Utilities.ProjectCreation/NuspecReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
Expand All @@ -13,17 +14,15 @@ namespace Microsoft.Build.Utilities.ProjectCreation
{
internal class NuspecReader
{
private static readonly XNamespace NuspecNamespace = "http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd";

private readonly XDocument _document;

private readonly XmlNamespaceManager _namespaceManager = new XmlNamespaceManager(new NameTable());

public NuspecReader(string contents)
{
_document = XDocument.Parse(contents);

_namespaceManager.AddNamespace("ns", NuspecNamespace.NamespaceName);
string ns = GetNamespace(_document);
_namespaceManager.AddNamespace("ns", ns);
}

public NuspecReader(FileInfo fileInfo)
Expand Down Expand Up @@ -125,6 +124,21 @@ public IEnumerable<string> PackageTypes

public string? Version => GetElement("version");

private static string GetNamespace(XDocument document)
{
XPathNavigator navigator = document.CreateNavigator();
navigator.MoveToFollowing(XPathNodeType.Element);

IDictionary<string, string> namespaces = navigator.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml);

if (namespaces.Count != 1)
{
throw new XmlException($"Unabled to determine nuspec XML namespace. Namespaces in scope: '{string.Join(",", new Dictionary<string, string>(namespaces))}'.");
}

return namespaces.Values.Single();
}

private IEnumerable<PackageContentFileEntry> GetContentFiles()
{
foreach (XElement file in _document.XPathSelectElements("//ns:package/ns:metadata/ns:contentFiles/ns:files", _namespaceManager))
Expand Down

0 comments on commit db652a8

Please sign in to comment.