Skip to content

Commit db652a8

Browse files
authored
Support any namespace in NuspecReader (#278)
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.
1 parent 1741100 commit db652a8

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

src/Microsoft.Build.Utilities.ProjectCreation.UnitTests/NuspecReaderTests.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,29 @@ public void LicenseExpressionIsNullForFileLicenses()
3434
nuspec.LicenseVersion.ShouldBeNull();
3535
nuspec.LicenseUrl.ShouldBeNull();
3636
}
37+
38+
// List of namespaces from https://github.com/NuGet/NuGet.Client/blob/6917e6c883d45f45672e20d4b1c45758dad2fa84/src/NuGet.Core/NuGet.Packaging/PackageCreation/Authoring/ManifestSchemaUtility.cs#L23-L50
39+
[Theory]
40+
[InlineData("http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd")]
41+
[InlineData("http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd")]
42+
[InlineData("http://schemas.microsoft.com/packaging/2011/10/nuspec.xsd")]
43+
[InlineData("http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd")]
44+
[InlineData("http://schemas.microsoft.com/packaging/2013/01/nuspec.xsd")]
45+
[InlineData("http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd")]
46+
public void ReaderCanParseKnownXmlNamespaces(string xmlns)
47+
{
48+
string contents =
49+
$@"<package xmlns=""{xmlns}"">
50+
<metadata>
51+
<id>PackageL</id>
52+
<version>16.4.60</version>
53+
</metadata>
54+
</package>";
55+
56+
NuspecReader nuspec = new NuspecReader(contents);
57+
58+
nuspec.Id.ShouldBe("PackageL");
59+
nuspec.Version.ShouldBe("16.4.60");
60+
}
3761
}
3862
}

src/Microsoft.Build.Utilities.ProjectCreation/NuspecReader.cs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System;
66
using System.Collections.Generic;
77
using System.IO;
8+
using System.Linq;
89
using System.Xml;
910
using System.Xml.Linq;
1011
using System.Xml.XPath;
@@ -13,17 +14,15 @@ namespace Microsoft.Build.Utilities.ProjectCreation
1314
{
1415
internal class NuspecReader
1516
{
16-
private static readonly XNamespace NuspecNamespace = "http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd";
17-
1817
private readonly XDocument _document;
19-
2018
private readonly XmlNamespaceManager _namespaceManager = new XmlNamespaceManager(new NameTable());
2119

2220
public NuspecReader(string contents)
2321
{
2422
_document = XDocument.Parse(contents);
2523

26-
_namespaceManager.AddNamespace("ns", NuspecNamespace.NamespaceName);
24+
string ns = GetNamespace(_document);
25+
_namespaceManager.AddNamespace("ns", ns);
2726
}
2827

2928
public NuspecReader(FileInfo fileInfo)
@@ -125,6 +124,21 @@ public IEnumerable<string> PackageTypes
125124

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

127+
private static string GetNamespace(XDocument document)
128+
{
129+
XPathNavigator navigator = document.CreateNavigator();
130+
navigator.MoveToFollowing(XPathNodeType.Element);
131+
132+
IDictionary<string, string> namespaces = navigator.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml);
133+
134+
if (namespaces.Count != 1)
135+
{
136+
throw new XmlException($"Unabled to determine nuspec XML namespace. Namespaces in scope: '{string.Join(",", new Dictionary<string, string>(namespaces))}'.");
137+
}
138+
139+
return namespaces.Values.Single();
140+
}
141+
128142
private IEnumerable<PackageContentFileEntry> GetContentFiles()
129143
{
130144
foreach (XElement file in _document.XPathSelectElements("//ns:package/ns:metadata/ns:contentFiles/ns:files", _namespaceManager))

0 commit comments

Comments
 (0)