SergeiM.Xembly 0.2.0

dotnet add package SergeiM.Xembly --version 0.2.0
                    
NuGet\Install-Package SergeiM.Xembly -Version 0.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SergeiM.Xembly" Version="0.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SergeiM.Xembly" Version="0.2.0" />
                    
Directory.Packages.props
<PackageReference Include="SergeiM.Xembly" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SergeiM.Xembly --version 0.2.0
                    
#r "nuget: SergeiM.Xembly, 0.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SergeiM.Xembly@0.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SergeiM.Xembly&version=0.2.0
                    
Install as a Cake Addin
#tool nuget:?package=SergeiM.Xembly&version=0.2.0
                    
Install as a Cake Tool

SergeiM.Xembly - XML Modifying Imperative Language for .NET

GitHub Actions Workflow Status NuGet Hits-of-Code GitHub License

Xembly is an Assembly-like imperative programming language for data manipulation in XML documents. It is a much simpler alternative to DOM, XSLT, and XQuery.

This is a .NET (C#) implementation of the original Java library by Yegor Bugayenko.

Quick Start

Installation

dotnet add package SergeiM.Xembly

Basic Usage

using SergeiM.Xembly;

// Create directives
var directives = new Directives()
    .Add("root")
    .Add("order")
    .Attr("id", "553")
    .Set("$140.00");

// Generate XML
var xembler = new Xembler(directives);
string xml = xembler.Xml();

// Output: <root><order id="553">$140.00</order></root>

Why Xembly?

Suppose you have an XML document:

<orders>
  <order id="553">
    <amount>$45.00</amount>
  </order>
</orders>

You want to change the amount of order #553 from $45.00 to $140.00. With Xembly, you write:

var directives = new Directives()
    .Add("orders")
    .Add("order")
    .Attr("id", "553")
    .Add("amount")
    .Set("$140.00");

Much simpler than DOM manipulation or XSLT transformations!

Supported Directives

Directive Description Example
ADD Adds new child node .Add("order")
ADDIF Adds child node if not exists .AddIf("order")
SET Sets text content .Set("$140.00")
ATTR Sets attribute .Attr("id", "553")
UP Moves to parent .Up()
REMOVE Removes nodes .Remove()
PUSH Saves cursor position .Push()
POP Restores cursor position .Pop()
XPATH Navigate using XPath .XPath("//order[@id='553']")
XSET Set text from XPath .XSet("count(//order)")
XATTR Set attribute from XPath .XAttr("total", "sum(//price)")
CDATA Add CDATA section .CData("<script>...</script>")
PI Add processing instruction .Pi("xml-stylesheet", "type='text/xsl'")
STRICT Validate cursor state .Strict(1)
NS Define XML namespace .Ns("ns", "http://example.com/ns")

More Examples

Using Script Syntax

var directives = new Directives("""
    ADD 'orders';
    ADD 'order';
    ATTR 'id', '553';
    ADD 'amount';
    SET '$140.00';
    """);

var xml = new Xembler(directives).Xml();
// Output: <orders><order id="553"><amount>$140.00</amount></order></orders>

XPath Navigation

var directives = new Directives()
    .Add("root")
    .Add("order").Attr("id", "1").Set("100").Up()
    .Add("order").Attr("id", "2").Set("200").Up()
    .XPath("//order[@id='2']")
    .Set("250");

var xml = new Xembler(directives).Xml();
// Changes the value of order with id='2' to 250

Multiple Nodes

var directives = new Directives()
    .Add("root")
    .Add("item")
    .Set("First")
    .Up()
    .Add("item")
    .Set("Second");

var xml = new Xembler(directives).Xml();
// Output: <root><item>First</item><item>Second</item></root>

Stack Operations (PUSH/POP)

Save and restore cursor position using stack operations:

var directives = new Directives()
    .Add("catalog")
    .Add("books")
    .Push()                      // Save position at <books>
    .Add("book").Attr("id", "1")
    .Add("title").Set("First Book").Up().Up()
    .Pop()                       // Return to <books>
    .Add("book").Attr("id", "2")
    .Add("title").Set("Second Book");

var xml = new Xembler(directives).Xml();
// Both books are added under <books>, even though we navigated deep into the first book

Error Handling

try
{
    var directives = new Directives("INVALID 'test';");
    new Xembler(directives).Xml();
}
catch (ParsingException ex)
{
    Console.WriteLine($"Parse error at line {ex.Line}, column {ex.Column}: {ex.Message}");
}

try
{
    var directives = new Directives()
        .Add("root")
        .Strict(2); // Expecting 2 nodes, but only have 1
    new Xembler(directives).Xml();
}
catch (StrictException ex)
{
    Console.WriteLine($"Validation error: {ex.Message}");
}

Exception Types

Exception Description Usage
XemblyException Base exception for all Xembly errors Catch-all for any Xembly operation
ParsingException Script parsing errors with line/column info Invalid script syntax
CursorException Cursor operation errors Invalid navigation, empty cursor
StrictException Validation failures STRICT directive violations

Modifying Existing Documents

var document = new XmlDocument();
document.LoadXml("<root><existing>node</existing></root>");

var directives = new Directives()
    .Add("new")
    .Set("value");

new Xembler(directives).Apply(document);
// Document now has: <root><existing>node</existing><new>value</new></root>

Building from Source

dotnet build

Running Tests

dotnet test

References

License

MIT License - see LICENSE.txt for details.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.2.0 107 1/7/2026
0.1.0 95 1/6/2026