JSFiddle - React, Tailwind, and code Playground

HTML

<body><div></div></body>

JavaScript

// XML Text element
var XMLTextElement = function (text) {
    this.text = text;
}

XMLTextElement.prototype.toString = function () {
    return this.text;
}

// XML Builder
var XMLBuilder = function (nodeName, parent) {
    this.nodeName = nodeName;
    this.parent = parent;
    this.elements = [];
    this.attributes = {};
};

XMLBuilder.prototype.element = function(nodeName, attributes) {
    var element = new XMLBuilder(nodeName, this);
    if (attributes != null) {
        element.attributes = attributes;
    }
    this.elements.push(element);
    return element;
}

XMLBuilder.prototype.text = function(text) {
    this.elements.push(new XMLTextElement(text));
}

XMLBuilder.prototype.toString = function () {
    var result = '';
    
    if (this.parent == null) { // Root element
        result += '<?xml version="1.0" encoding="UTF-8"?>';
    }
    
    result += '<' + this.nodeName;
    
    for (var attName in this.attributes) {
        result += ' ' + attName + '="' + this.attributes[attName] + '"';
    }
    
    if (this.elements.length == 0) {
        result += ' />';
    } else {
        result += '>';
        
        for (var i = 0; i < this.elements.length; i++) {
            result += this.elements[i].toString();
        }
        
        result += '</' + this.nodeName + '>';
    }
    
    return result;
}

// Usage

// Create new builder with a root element
var builder = new XMLBuilder("rootElement");

// Add some text
builder.text('Some text');

// Create an element with attributes and add some text to it
var element = builder.element("someElement", {'attr':'value'});
element.text("This is a text.");

builder.text('Some more Text');
builder.element("emptyElement");
builder.text('Even some more text');

// Empty element with attributes
builder.element("emptyWithAttributes", {'a1': 'val1', 'a2' : 'val2'});

// Add text to HTML
$('div').text(builder.toString());