Initial commit
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
using System.Xml;
|
||||
|
||||
namespace aeqw89.tools.Publish;
|
||||
|
||||
internal sealed class Content : Item {
|
||||
public Content(XmlElement node) : base(node) { }
|
||||
}
|
||||
@@ -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<Item> GetChildElements() {
|
||||
foreach (var e in Node.ChildNodes.OfType<XmlElement>())
|
||||
yield return new Item(e);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Xml;
|
||||
|
||||
namespace aeqw89.tools.Publish;
|
||||
|
||||
internal class ItemGroup {
|
||||
private readonly XmlElement _element;
|
||||
public List<Item> Items { get; }
|
||||
|
||||
public void Remove() {
|
||||
_element.ParentNode!.RemoveChild(_element);
|
||||
}
|
||||
|
||||
public ItemGroup(XmlElement element) {
|
||||
_element = element;
|
||||
Items = element.ChildNodes
|
||||
.OfType<XmlElement>()
|
||||
.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));
|
||||
}
|
||||
}
|
||||
@@ -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 <Version>
|
||||
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 <Version>
|
||||
var child = (XmlElement)Node.SelectSingleNode("./Version")!;
|
||||
child.InnerText = version ?? string.Empty;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using System.Xml;
|
||||
|
||||
namespace aeqw89.tools.Publish;
|
||||
|
||||
internal class Project {
|
||||
public string Path { get; }
|
||||
private XmlDocument Document { get; }
|
||||
public List<PropertyGroup> PropertyGroups { get; }
|
||||
public List<ItemGroup> ItemGroups { get; }
|
||||
|
||||
private Project(string path, XmlDocument doc) {
|
||||
Path = path;
|
||||
Document = doc;
|
||||
|
||||
// Build PropertyGroups
|
||||
PropertyGroups = doc.DocumentElement!
|
||||
.SelectNodes("./PropertyGroup")!
|
||||
.OfType<XmlElement>()
|
||||
.Select(e => new PropertyGroup(e))
|
||||
.ToList();
|
||||
|
||||
// Build ItemGroups (+ their Items)
|
||||
ItemGroups = doc.DocumentElement!
|
||||
.SelectNodes("./ItemGroup")!
|
||||
.OfType<XmlElement>()
|
||||
.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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using System.Xml;
|
||||
|
||||
namespace aeqw89.tools.Publish;
|
||||
|
||||
internal sealed class ProjectReference : Item {
|
||||
public ProjectReference(XmlElement node) : base(node) { }
|
||||
}
|
||||
@@ -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<XmlElement>().Count();
|
||||
|
||||
public void Remove() => _element.ParentNode!.RemoveChild(_element);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user