mrkeyoor.com_
Sat 08 Aug 21:57 UTC
npmUtilsupdated 08 Aug 2026

xmlcreate

xmlcreate is a dependency-free XML tree builder for Node.js. You create a document, add declarations, DTD nodes, elements, attributes, text, CDATA, comments, references, and processing instructions, then serialize the finished tree. Every child node has an up() method for fluent navigation back to its parent. The package escapes text and can perform basic well-formedness checks, but it does not parse XML or validate a document against a schema.

Verdict

A capable small builder when you need explicit XML constructs and are comfortable owning the document structure. For new general-purpose XML work, xmlbuilder2 has broader capabilities and a healthier direct-use ecosystem.

API stability4/5The 2.x API has stayed centered on document(), node-specific creation methods, mutable properties, up(), and toString since the 2.0 rewrite. Version 2.0.4 only reports dependency updates and bug fixes after that redesign. The explicit node model is predictable, though another major could be disruptive because 2.0 itself was described as an API rewrite and simplification.
Docs4/5The README gives a complete declaration, public DTD, namespace-attribute, nested-element, and serialization example. Versioned generated documentation describes every node class, option, return type, default, and XML restriction, including the difference between character data and attribute text. It lacks a compact cookbook, so common tasks require reading individual class pages or deciphering a long fluent example.
Maintenance2/5The latest npm release, 2.0.4, dates to October 2021 and the repository's last push was in April 2023. The repository is not archived and reports only three open issues and pull requests, which is compatible with a finished small utility, but there is little evidence of ongoing releases or current runtime testing. Depend on the present feature set rather than expecting new capabilities.
Ecosystem2/5The package records 3,710,667 weekly downloads, but its repository has only 5 stars and its main visible downstream use is js2xmlparser, which can account for substantial transitive installation. Included declarations and zero dependencies are positives. Direct community material, integrations, and extension packages are sparse compared with xmlbuilder2 and broader XML toolkits.

Use it if

  • You need explicit control over XML nodes and their order rather than an automatic object-to-XML mapping
  • You need DTD declarations, CDATA, comments, character or entity references, and processing instructions in a small Node package
  • You want included TypeScript declarations, no runtime dependencies, and configurable pretty-printing
  • You already receive XmlElement instances from js2xmlparser or another xmlcreate-based component
Skip it if

Setup reality

`npm install xmlcreate` has no peer dependencies, runtime dependencies, native modules, credentials, or config files. It is written in TypeScript and publishes declarations through its `typings` entry, while its runtime is CommonJS. The practical friction is the tree API. Methods return the child they just created, so adding a sibling means saving parent variables or calling `up()` the correct number of times. For anything beyond a tiny document, named variables are clearer than one deep fluent chain. A document may have one declaration, one DTD, and exactly one root element in the required order when validation is enabled. Validation is basic well-formedness checking, not XSD, Relax NG, or business-rule validation. Character data and attribute text escape reserved characters automatically; CDATA, comments, processing instructions, DTD declaration fragments, entity references, and names have their own XML restrictions and can throw. Some node options can replace invalid characters with U+FFFD, but that silently changes data, so rejection is safer for identifiers and signed payloads. Empty elements self-close by default. Serialization is pretty by default with four-space indentation, newline line endings, and single quotes for attributes; set formatting explicitly when snapshots, partner systems, or signatures care about exact bytes. Namespace support is manual: use prefixed names and add matching xmlns attributes yourself. The complete tree and output string stay in memory, so this is best for small and medium documents rather than multi-gigabyte exports.

Patterns

Build a complete XML documentcreate-document

const { document } = require('xmlcreate');

const doc = document();
doc.decl({ encoding: 'UTF-8' });
const root = doc.element({ name: 'catalog' });
root.element({ name: 'title' }).charData({ charData: 'Summer' });

console.log(doc.toString());

A validated document accepts exactly one root element. Keep a reference to the parent when adding several siblings.

Add escaped attribute valuesadd-attributes

const product = root.element({ name: 'product' });
product.attribute({ name: 'id' }).text({ charData: 'sku-42' });
product.attribute({ name: 'label' }).text({ charData: 'Tea & biscuits' });

Attribute values are child text nodes, not a value option on attribute(). Reserved characters such as & are escaped automatically.

Navigate back to add siblingsadd-sibling-elements

const list = root.element({ name: 'items' });
list.element({ name: 'item' })
  .charData({ charData: 'one' })
  .up()
  .up()
  .element({ name: 'item' })
  .charData({ charData: 'two' });

charData().up() returns the item element, and the second up() returns items. Named variables are safer once chains get deeper.

Write character data safelyescape-text

root.element({ name: 'expression' }).charData({
  charData: 'a < b && b > 0',
});

charData escapes ampersands, opening angle brackets, and a closing angle bracket when needed to avoid the forbidden ]]> sequence.

Add a CDATA sectionwrite-cdata

root.element({ name: 'script' }).cdata({
  charData: 'if (a < b) console.log(a);',
});

CDATA content cannot contain ]]> as one section. Split hostile or arbitrary content yourself, or use charData for automatic escaping.

Add document and element commentsadd-comment

doc.comment({ charData: 'generated file' });
root.comment({ charData: 'items start here' });

With validation enabled, declaration ordering still matters, and XML comments cannot contain invalid comment sequences such as double hyphens.

Add a processing instructionadd-processing-instruction

doc.procInst({
  target: 'xml-stylesheet',
  content: 'type="text/xsl" href="catalog.xsl"',
});

The package writes the content as processing-instruction data. You are responsible for constructing its pseudo-attributes correctly.

Create prefixed names with a namespace declarationdeclare-namespace

const feed = doc.element({ name: 'atom:feed' });
feed.attribute({ name: 'xmlns:atom' }).text({
  charData: 'http://www.w3.org/2005/Atom',
});
feed.element({ name: 'atom:title' }).charData({ charData: 'Updates' });

Namespace handling is manual. xmlcreate writes the prefix and xmlns attribute but does not associate or validate the namespace URI.

Force an explicit closing tagcontrol-empty-tags

root.element({
  name: 'description',
  useSelfClosingTagIfEmpty: false,
});

Empty elements self-close by default. This per-element option emits <description></description> when a consumer distinguishes the lexical forms.

Add character and entity referenceswrite-references

const text = root.element({ name: 'text' });
text.charData({ charData: 'Copyright ' });
text.charRef({ char: '©', hex: true });
text.charData({ charData: ' Acme ' });
text.entityRef({ name: 'registered' });

An entity reference is only a reference. Declare custom entities in a DTD or ensure the receiving environment already knows them.

Build a DTD with an internal subsetdefine-internal-dtd

const doc = document();
doc.decl();
const dtd = doc.dtd({ name: 'note' });
dtd.element({ charData: 'note (to,from)' });
dtd.element({ charData: 'to (#PCDATA)' });
dtd.element({ charData: 'from (#PCDATA)' });
doc.element({ name: 'note' });

DTD declaration bodies are supplied as strings. Basic validation is not a substitute for validating the resulting grammar or document against the DTD.

Control output formattingformat-xml

const xml = doc.toString({
  pretty: true,
  indent: '  ',
  newline: '\n',
  doubleQuotes: true,
});

Defaults are pretty output, four-space indentation, newline line endings, and single-quoted attributes. Set all options for deterministic fixtures.

Alternatives

PackageRegistryPick it when
xmlbuilder2npmYou want a more widely used fluent builder with namespace helpers, parsing, conversion, and callback APIs
xml-jsnpmYou need both XML-to-JavaScript and JavaScript-to-XML conversion rather than manual tree construction
xml-writernpmYou prefer a sequential writer-style API for emitting XML without navigating a retained node tree