From 03c5efe27b3263eff6e27fe79ed866fd0732ba8f Mon Sep 17 00:00:00 2001 From: qwsdcvghyu89 <61093706+qwsdcvghyu89@users.noreply.github.com> Date: Sun, 21 Sep 2025 16:42:18 +1000 Subject: [PATCH] Initial commit --- .gitignore | 5 ++ aeqw89.xml.ProjectFile.sln | 16 ++++++ aeqw89.xml.ProjectFile/Content.cs | 7 +++ aeqw89.xml.ProjectFile/Item.cs | 55 +++++++++++++++++++ aeqw89.xml.ProjectFile/ItemGroup.cs | 26 +++++++++ aeqw89.xml.ProjectFile/PackageReference.cs | 30 ++++++++++ aeqw89.xml.ProjectFile/Project.cs | 54 ++++++++++++++++++ aeqw89.xml.ProjectFile/ProjectReference.cs | 7 +++ aeqw89.xml.ProjectFile/PropertyGroup.cs | 28 ++++++++++ .../aeqw89.xml.ProjectFile.csproj | 9 +++ aeqw89.xml.csproj.sln | 16 ++++++ aeqw89.xml.csproj/Content.cs | 7 +++ aeqw89.xml.csproj/Item.cs | 55 +++++++++++++++++++ aeqw89.xml.csproj/ItemGroup.cs | 26 +++++++++ aeqw89.xml.csproj/PackageReference.cs | 30 ++++++++++ aeqw89.xml.csproj/Project.cs | 54 ++++++++++++++++++ aeqw89.xml.csproj/ProjectReference.cs | 7 +++ aeqw89.xml.csproj/PropertyGroup.cs | 28 ++++++++++ aeqw89.xml.csproj/aeqw89.xml.csproj.csproj | 10 ++++ 19 files changed, 470 insertions(+) create mode 100644 .gitignore create mode 100644 aeqw89.xml.ProjectFile.sln create mode 100644 aeqw89.xml.ProjectFile/Content.cs create mode 100644 aeqw89.xml.ProjectFile/Item.cs create mode 100644 aeqw89.xml.ProjectFile/ItemGroup.cs create mode 100644 aeqw89.xml.ProjectFile/PackageReference.cs create mode 100644 aeqw89.xml.ProjectFile/Project.cs create mode 100644 aeqw89.xml.ProjectFile/ProjectReference.cs create mode 100644 aeqw89.xml.ProjectFile/PropertyGroup.cs create mode 100644 aeqw89.xml.ProjectFile/aeqw89.xml.ProjectFile.csproj create mode 100644 aeqw89.xml.csproj.sln create mode 100644 aeqw89.xml.csproj/Content.cs create mode 100644 aeqw89.xml.csproj/Item.cs create mode 100644 aeqw89.xml.csproj/ItemGroup.cs create mode 100644 aeqw89.xml.csproj/PackageReference.cs create mode 100644 aeqw89.xml.csproj/Project.cs create mode 100644 aeqw89.xml.csproj/ProjectReference.cs create mode 100644 aeqw89.xml.csproj/PropertyGroup.cs create mode 100644 aeqw89.xml.csproj/aeqw89.xml.csproj.csproj diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..add57be --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +bin/ +obj/ +/packages/ +riderModule.iml +/_ReSharper.Caches/ \ No newline at end of file diff --git a/aeqw89.xml.ProjectFile.sln b/aeqw89.xml.ProjectFile.sln new file mode 100644 index 0000000..470a348 --- /dev/null +++ b/aeqw89.xml.ProjectFile.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "aeqw89.xml.ProjectFile", "aeqw89.xml.ProjectFile\aeqw89.xml.ProjectFile.csproj", "{F2871BF4-713B-4487-867E-E409AFCDDC9B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F2871BF4-713B-4487-867E-E409AFCDDC9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F2871BF4-713B-4487-867E-E409AFCDDC9B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F2871BF4-713B-4487-867E-E409AFCDDC9B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F2871BF4-713B-4487-867E-E409AFCDDC9B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/aeqw89.xml.ProjectFile/Content.cs b/aeqw89.xml.ProjectFile/Content.cs new file mode 100644 index 0000000..403f889 --- /dev/null +++ b/aeqw89.xml.ProjectFile/Content.cs @@ -0,0 +1,7 @@ +using System.Xml; + +namespace aeqw89.xml.ProjectFile; + +public sealed class Content : Item { + public Content(XmlElement node) : base(node) { } +} \ No newline at end of file diff --git a/aeqw89.xml.ProjectFile/Item.cs b/aeqw89.xml.ProjectFile/Item.cs new file mode 100644 index 0000000..16f8f2e --- /dev/null +++ b/aeqw89.xml.ProjectFile/Item.cs @@ -0,0 +1,55 @@ +using System.Xml; + +namespace aeqw89.xml.ProjectFile; + +public class Item { + public string ElementName { get; protected set; } + public string Include { + get => Node.GetAttribute("Include"); + set => Node.SetAttribute("Include", value); + } + + public string Version { + get => Node.GetAttribute("Version"); + set => Node.SetAttribute("Version", value); + } + + public string? Value { + get => Node.InnerText; + set { Node.InnerText = value ?? string.Empty; } + } + public XmlElement Node { get; } + + protected Item(XmlElement node) { + Node = node; + ElementName = node.Name; + } + + public static Item FromElement(XmlElement element) { + return element.Name switch { + "PackageReference" => new PackageReference(element), + "ProjectReference" => new ProjectReference(element), + "Content" => new Content(element), + _ => new Item(element), + }; + } + + public void AddChild(Item child) { + var imported = Node.OwnerDocument!.ImportNode(child.Node, true); + Node.AppendChild(imported); + } + + public string? GetAttribute(string name) => Node.HasAttribute(name) ? Node.GetAttribute(name) : null; + public void SetAttribute(string name, string? value) { + if (value is null) { + if (Node.HasAttribute(name)) Node.RemoveAttribute(name); + return; + } + Node.SetAttribute(name, value); + } + + public IEnumerable GetChildElements() { + foreach (var e in Node.ChildNodes.OfType()) + yield return new Item(e); + } +} \ No newline at end of file diff --git a/aeqw89.xml.ProjectFile/ItemGroup.cs b/aeqw89.xml.ProjectFile/ItemGroup.cs new file mode 100644 index 0000000..1310927 --- /dev/null +++ b/aeqw89.xml.ProjectFile/ItemGroup.cs @@ -0,0 +1,26 @@ +using System.Xml; + +namespace aeqw89.xml.ProjectFile; + +public class ItemGroup { + private readonly XmlElement _element; + public List Items { get; } + + public void Remove() { + _element.ParentNode!.RemoveChild(_element); + } + + public ItemGroup(XmlElement element) { + _element = element; + Items = element.ChildNodes + .OfType() + .Select(Item.FromElement) + .ToList(); + } + + public void Add(Item item) { + var imported = _element.OwnerDocument!.ImportNode(item.Node, true); + _element.AppendChild(imported); + Items.Add(Item.FromElement((XmlElement)imported)); + } +} \ No newline at end of file diff --git a/aeqw89.xml.ProjectFile/PackageReference.cs b/aeqw89.xml.ProjectFile/PackageReference.cs new file mode 100644 index 0000000..f580445 --- /dev/null +++ b/aeqw89.xml.ProjectFile/PackageReference.cs @@ -0,0 +1,30 @@ +using System.Xml; + +namespace aeqw89.xml.ProjectFile; + +public sealed class PackageReference : Item { + public PackageReference(XmlElement node) : base(node) { } + + // inside PackageReference + public string? GetPackageVersion() { + // Prefer attribute, then child + var attr = GetAttribute("Version"); + if (!string.IsNullOrEmpty(attr)) return attr; + + var child = Node.SelectSingleNode("./Version") as XmlElement; + return child?.InnerText; + } + + public void SetPackageVersion(string? version) { + if (Node.HasAttribute("Version") || (Node.SelectSingleNode("./Version") == null)) { + // If attribute exists (or no child yet), use attribute + SetAttribute("Version", version); + return; + } + + // Else write to existing child + var child = (XmlElement)Node.SelectSingleNode("./Version")!; + child.InnerText = version ?? string.Empty; + } + +} \ No newline at end of file diff --git a/aeqw89.xml.ProjectFile/Project.cs b/aeqw89.xml.ProjectFile/Project.cs new file mode 100644 index 0000000..1863132 --- /dev/null +++ b/aeqw89.xml.ProjectFile/Project.cs @@ -0,0 +1,54 @@ +using System.Xml; + +namespace aeqw89.xml.ProjectFile; + +public class Project { + public string Path { get; } + private XmlDocument Document { get; } + public List PropertyGroups { get; } + public List ItemGroups { get; } + + private Project(string path, XmlDocument doc) { + Path = path; + Document = doc; + + // Build PropertyGroups + PropertyGroups = doc.DocumentElement! + .SelectNodes("./PropertyGroup")! + .OfType() + .Select(e => new PropertyGroup(e)) + .ToList(); + + // Build ItemGroups (+ their Items) + ItemGroups = doc.DocumentElement! + .SelectNodes("./ItemGroup")! + .OfType() + .Select(e => new ItemGroup(e)) + .ToList(); + + // Ensure at least one ItemGroup exists (some csprojs omit it until first item is added) + if (ItemGroups.Count == 0) { + var ig = doc.CreateElement("ItemGroup", doc.DocumentElement!.NamespaceURI); + doc.DocumentElement!.AppendChild(ig); + ItemGroups.Add(new ItemGroup((XmlElement)ig)); + } + } + + public static Project Load(string path) { + var doc = new XmlDocument(); + doc.PreserveWhitespace = false; + doc.Load(path); + return new Project(path, doc); + } + + public void Save() { + var settings = new XmlWriterSettings { + Indent = true, + IndentChars = " ", + NewLineChars = Environment.NewLine, + NewLineHandling = NewLineHandling.Replace + }; + using var writer = XmlWriter.Create(Path, settings); + Document.Save(writer); + } +} \ No newline at end of file diff --git a/aeqw89.xml.ProjectFile/ProjectReference.cs b/aeqw89.xml.ProjectFile/ProjectReference.cs new file mode 100644 index 0000000..4dafa16 --- /dev/null +++ b/aeqw89.xml.ProjectFile/ProjectReference.cs @@ -0,0 +1,7 @@ +using System.Xml; + +namespace aeqw89.xml.ProjectFile; + +public sealed class ProjectReference : Item { + public ProjectReference(XmlElement node) : base(node) { } +} \ No newline at end of file diff --git a/aeqw89.xml.ProjectFile/PropertyGroup.cs b/aeqw89.xml.ProjectFile/PropertyGroup.cs new file mode 100644 index 0000000..ec870f4 --- /dev/null +++ b/aeqw89.xml.ProjectFile/PropertyGroup.cs @@ -0,0 +1,28 @@ +using System.Xml; + +namespace aeqw89.xml.ProjectFile; + +public class PropertyGroup { + private readonly XmlElement _element; + public PropertyGroup(XmlElement element) => _element = element; + + public bool HasProperty(string name) => _element.SelectSingleNode($"./{name}") is XmlElement; + + public string GetProperty(string name) { + var node = _element.SelectSingleNode($"./{name}") as XmlElement; + return node?.InnerText ?? string.Empty; + } + + public void SetProperty(string name, string value) { + var node = _element.SelectSingleNode($"./{name}") as XmlElement; + if (node == null) { + node = _element.OwnerDocument!.CreateElement(name, _element.NamespaceURI); + _element.AppendChild(node); + } + node.InnerText = value ?? string.Empty; + } + + public int Count => _element.ChildNodes.OfType().Count(); + + public void Remove() => _element.ParentNode!.RemoveChild(_element); +} \ No newline at end of file diff --git a/aeqw89.xml.ProjectFile/aeqw89.xml.ProjectFile.csproj b/aeqw89.xml.ProjectFile/aeqw89.xml.ProjectFile.csproj new file mode 100644 index 0000000..17b910f --- /dev/null +++ b/aeqw89.xml.ProjectFile/aeqw89.xml.ProjectFile.csproj @@ -0,0 +1,9 @@ + + + + net9.0 + enable + enable + + + diff --git a/aeqw89.xml.csproj.sln b/aeqw89.xml.csproj.sln new file mode 100644 index 0000000..6b0d8b1 --- /dev/null +++ b/aeqw89.xml.csproj.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "aeqw89.xml.csproj", "aeqw89.xml.csproj\aeqw89.xml.csproj.csproj", "{F2871BF4-713B-4487-867E-E409AFCDDC9B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F2871BF4-713B-4487-867E-E409AFCDDC9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F2871BF4-713B-4487-867E-E409AFCDDC9B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F2871BF4-713B-4487-867E-E409AFCDDC9B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F2871BF4-713B-4487-867E-E409AFCDDC9B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/aeqw89.xml.csproj/Content.cs b/aeqw89.xml.csproj/Content.cs new file mode 100644 index 0000000..03a7e7a --- /dev/null +++ b/aeqw89.xml.csproj/Content.cs @@ -0,0 +1,7 @@ +using System.Xml; + +namespace aeqw89.tools.Publish; + +internal sealed class Content : Item { + public Content(XmlElement node) : base(node) { } +} \ No newline at end of file diff --git a/aeqw89.xml.csproj/Item.cs b/aeqw89.xml.csproj/Item.cs new file mode 100644 index 0000000..6a4ed7e --- /dev/null +++ b/aeqw89.xml.csproj/Item.cs @@ -0,0 +1,55 @@ +using System.Xml; + +namespace aeqw89.tools.Publish; + +internal class Item { + public string ElementName { get; protected set; } + public string Include { + get => Node.GetAttribute("Include"); + set => Node.SetAttribute("Include", value); + } + + public string Version { + get => Node.GetAttribute("Version"); + set => Node.SetAttribute("Version", value); + } + + public string? Value { + get => Node.InnerText; + set { Node.InnerText = value ?? string.Empty; } + } + public XmlElement Node { get; } + + protected Item(XmlElement node) { + Node = node; + ElementName = node.Name; + } + + public static Item FromElement(XmlElement element) { + return element.Name switch { + "PackageReference" => new PackageReference(element), + "ProjectReference" => new ProjectReference(element), + "Content" => new Content(element), + _ => new Item(element), + }; + } + + public void AddChild(Item child) { + var imported = Node.OwnerDocument!.ImportNode(child.Node, true); + Node.AppendChild(imported); + } + + public string? GetAttribute(string name) => Node.HasAttribute(name) ? Node.GetAttribute(name) : null; + public void SetAttribute(string name, string? value) { + if (value is null) { + if (Node.HasAttribute(name)) Node.RemoveAttribute(name); + return; + } + Node.SetAttribute(name, value); + } + + public IEnumerable GetChildElements() { + foreach (var e in Node.ChildNodes.OfType()) + yield return new Item(e); + } +} \ No newline at end of file diff --git a/aeqw89.xml.csproj/ItemGroup.cs b/aeqw89.xml.csproj/ItemGroup.cs new file mode 100644 index 0000000..88824a4 --- /dev/null +++ b/aeqw89.xml.csproj/ItemGroup.cs @@ -0,0 +1,26 @@ +using System.Xml; + +namespace aeqw89.tools.Publish; + +internal class ItemGroup { + private readonly XmlElement _element; + public List Items { get; } + + public void Remove() { + _element.ParentNode!.RemoveChild(_element); + } + + public ItemGroup(XmlElement element) { + _element = element; + Items = element.ChildNodes + .OfType() + .Select(Item.FromElement) + .ToList(); + } + + public void Add(Item item) { + var imported = _element.OwnerDocument!.ImportNode(item.Node, true); + _element.AppendChild(imported); + Items.Add(Item.FromElement((XmlElement)imported)); + } +} \ No newline at end of file diff --git a/aeqw89.xml.csproj/PackageReference.cs b/aeqw89.xml.csproj/PackageReference.cs new file mode 100644 index 0000000..7413954 --- /dev/null +++ b/aeqw89.xml.csproj/PackageReference.cs @@ -0,0 +1,30 @@ +using System.Xml; + +namespace aeqw89.tools.Publish; + +internal sealed class PackageReference : Item { + public PackageReference(XmlElement node) : base(node) { } + + // inside PackageReference + public string? GetPackageVersion() { + // Prefer attribute, then child + var attr = GetAttribute("Version"); + if (!string.IsNullOrEmpty(attr)) return attr; + + var child = Node.SelectSingleNode("./Version") as XmlElement; + return child?.InnerText; + } + + public void SetPackageVersion(string? version) { + if (Node.HasAttribute("Version") || (Node.SelectSingleNode("./Version") == null)) { + // If attribute exists (or no child yet), use attribute + SetAttribute("Version", version); + return; + } + + // Else write to existing child + var child = (XmlElement)Node.SelectSingleNode("./Version")!; + child.InnerText = version ?? string.Empty; + } + +} \ No newline at end of file diff --git a/aeqw89.xml.csproj/Project.cs b/aeqw89.xml.csproj/Project.cs new file mode 100644 index 0000000..c5d2e73 --- /dev/null +++ b/aeqw89.xml.csproj/Project.cs @@ -0,0 +1,54 @@ +using System.Xml; + +namespace aeqw89.tools.Publish; + +internal class Project { + public string Path { get; } + private XmlDocument Document { get; } + public List PropertyGroups { get; } + public List ItemGroups { get; } + + private Project(string path, XmlDocument doc) { + Path = path; + Document = doc; + + // Build PropertyGroups + PropertyGroups = doc.DocumentElement! + .SelectNodes("./PropertyGroup")! + .OfType() + .Select(e => new PropertyGroup(e)) + .ToList(); + + // Build ItemGroups (+ their Items) + ItemGroups = doc.DocumentElement! + .SelectNodes("./ItemGroup")! + .OfType() + .Select(e => new ItemGroup(e)) + .ToList(); + + // Ensure at least one ItemGroup exists (some csprojs omit it until first item is added) + if (ItemGroups.Count == 0) { + var ig = doc.CreateElement("ItemGroup", doc.DocumentElement!.NamespaceURI); + doc.DocumentElement!.AppendChild(ig); + ItemGroups.Add(new ItemGroup((XmlElement)ig)); + } + } + + public static Project Load(string path) { + var doc = new XmlDocument(); + doc.PreserveWhitespace = false; + doc.Load(path); + return new Project(path, doc); + } + + public void Save() { + var settings = new XmlWriterSettings { + Indent = true, + IndentChars = " ", + NewLineChars = Environment.NewLine, + NewLineHandling = NewLineHandling.Replace + }; + using var writer = XmlWriter.Create(Path, settings); + Document.Save(writer); + } +} \ No newline at end of file diff --git a/aeqw89.xml.csproj/ProjectReference.cs b/aeqw89.xml.csproj/ProjectReference.cs new file mode 100644 index 0000000..acf6799 --- /dev/null +++ b/aeqw89.xml.csproj/ProjectReference.cs @@ -0,0 +1,7 @@ +using System.Xml; + +namespace aeqw89.tools.Publish; + +internal sealed class ProjectReference : Item { + public ProjectReference(XmlElement node) : base(node) { } +} \ No newline at end of file diff --git a/aeqw89.xml.csproj/PropertyGroup.cs b/aeqw89.xml.csproj/PropertyGroup.cs new file mode 100644 index 0000000..56f966f --- /dev/null +++ b/aeqw89.xml.csproj/PropertyGroup.cs @@ -0,0 +1,28 @@ +using System.Xml; + +namespace aeqw89.tools.Publish; + +internal class PropertyGroup { + private readonly XmlElement _element; + public PropertyGroup(XmlElement element) => _element = element; + + public bool HasProperty(string name) => _element.SelectSingleNode($"./{name}") is XmlElement; + + public string GetProperty(string name) { + var node = _element.SelectSingleNode($"./{name}") as XmlElement; + return node?.InnerText ?? string.Empty; + } + + public void SetProperty(string name, string value) { + var node = _element.SelectSingleNode($"./{name}") as XmlElement; + if (node == null) { + node = _element.OwnerDocument!.CreateElement(name, _element.NamespaceURI); + _element.AppendChild(node); + } + node.InnerText = value ?? string.Empty; + } + + public int Count => _element.ChildNodes.OfType().Count(); + + public void Remove() => _element.ParentNode!.RemoveChild(_element); +} \ No newline at end of file diff --git a/aeqw89.xml.csproj/aeqw89.xml.csproj.csproj b/aeqw89.xml.csproj/aeqw89.xml.csproj.csproj new file mode 100644 index 0000000..85b4959 --- /dev/null +++ b/aeqw89.xml.csproj/aeqw89.xml.csproj.csproj @@ -0,0 +1,10 @@ + + + + Exe + net9.0 + enable + enable + + +