I was looking for something that looked like jquery for generating dom in C# (I don't need to parse). Unfortunately no luck in finding a lightweight solution so I created this simple class that is inherited from System.Xml.Linq.XElement. The key feature is that you can chain the operator like when using jquery in javascript so it's more fluent. It's not fully featured but it does what I need and if there is interest I can start a git.
public class DomElement : XElement
{
public DomElement(string name) : base(name)
{
}
public DomElement(string name, string value) : base(name, value)
{
}
public DomElement Css(string style, string value)
{
style = style.Trim();
value = value.Trim();
var existingStyles = new Dictionary<string, string>();
var xstyle = this.Attribute("style");
if (xstyle != null)
{
foreach (var s in xstyle.Value.Split(';'))
{
var keyValue = s.Split(':');
existingStyles.Add(keyValue[0], keyValue.Length < 2 ? null : keyValue[1]);
}
}
if (existingStyles.ContainsKey(style))
{
existingStyles[style] = value;
}
else
{
existingStyles.Add(style, value);
}
var styleString = string.Join(";", existingStyles.Select(s => $"{s.Key}:{s.Value}"));
this.SetAttributeValue("style", styleString);
return this;
}
public DomElement AddClass(string cssClass)
{
var existingClasses = new List<string>();
var xclass = this.Attribute("class");
if (xclass != null)
{
existingClasses.AddRange(xclass.Value.Split());
}
var addNewClasses = cssClass.Split().Where(e => !existingClasses.Contains(e));
existingClasses.AddRange(addNewClasses);
this.SetAttributeValue("class", string.Join(" ", existingClasses));
return this;
}
public DomElement Text(string text)
{
this.Value = text;
return this;
}
public DomElement Append(string text)
{
this.Add(text);
return this;
}
public DomElement Append(DomElement child)
{
this.Add(child);
return this;
}
}
Sample:
void Main()
{
var html = new DomElement("html")
.Append(new DomElement("head"))
.Append(new DomElement("body")
.Append(new DomElement("p")
.Append("This paragraph contains")
.Append(new DomElement("b", "bold"))
.Append(" text.")
)
.Append(new DomElement("p").Text("This paragraph has just plain text"))
)
;
html.ToString().Dump();
var table = new DomElement("table").AddClass("table table-sm").AddClass("table-striped")
.Append(new DomElement("thead")
.Append(new DomElement("tr")
.Append(new DomElement("td").Css("padding-left", "15px").Css("color", "red").Css("color", "blue")
.AddClass("from-now")
.Append(new DomElement("div").Text("Hi there"))
.Append(new DomElement("div").Text("Hey there"))
.Append(new DomElement("div", "Yo there"))
)
)
)
;
table.ToString().Dump();
}
output from above code:
<html>
<head />
<body>
<p>This paragraph contains<b>bold</b> text.</p>
<p>This paragraph has just plain text</p>
</body>
</html>
<table class="table table-sm table-striped">
<thead>
<tr>
<td style="padding-left:15px;color:blue" class="from-now">
<div>Hi there</div>
<div>Hey there</div>
<div>Yo there</div>
</td>
</tr>
</thead>
</table>