XMLBuilder Options

May 8, 2026 · View on GitHub

XML Builder can be used to build an XML string from a JS object. It supports the following options:

import XMLBuilder from 'fast-xml-builder';

const options = {
    ignoreAttributes: false
};

const builder = new XMLBuilder(options);
let xmlDataStr = builder.build(jObj);

arrayNodeName

When you build XML from an array, set arrayNodeName to wrap each element in a named tag.

const cars = [
    { color: "purple", type: "minivan", registration: "2020-02-03", capacity: 7 },
    { color: "orange", type: "SUV",     registration: "2021-05-17", capacity: 4 },
];
const builder = new XMLBuilder({ arrayNodeName: "car" });
const output = builder.build(cars);
<car>
    <color>purple</color>
    <type>minivan</type>
    <registration>2020-02-03</registration>
    <capacity>7</capacity>
</car>
<car>
    <color>orange</color>
    <type>SUV</type>
    <registration>2021-05-17</registration>
    <capacity>4</capacity>
</car>

attributeNamePrefix

Prefix used to identify attribute properties in the JS object so they can be recognized and stripped from tag names. Default: '@_'.

Avoid setting it to blank string as the builder can't distinguish it with other properties/tags.


attributesGroupName

Identifies a property in the JS object that groups all attributes for a tag. The builder strips this key and promotes its children as XML attributes.

This option is not supported when preserveOrder: true because attributes are already grouped in the ordered structure.


attributeValueProcessor

Customize how attribute values are serialized. Receives the attribute name and its raw value.

const options = {
    ignoreAttributes: false,
    attributeValueProcessor: (attrName, val) => val.toUpperCase()
};

Note: For stop nodes, attributeValueProcessor is skipped and values are written as-is.


cdataPropName

Identifies properties whose values should be wrapped in <![CDATA[...]]> blocks.

Example input:

{
    "any_name": {
        "person": {
            "phone": [122233344550, 122233344551, ""],
            "name": ["<some>Jack</some>Jack", "<some>Mohan</some>"],
            "blank": "",
            "regx": "^[ ].*$"
        }
    }
}

Code:

const options = {
    processEntities: false,
    format: true,
    ignoreAttributes: false,
    cdataPropName: "phone"
};
const builder = new XMLBuilder(options);
const xmlOutput = builder.build(input);

Output:

<any_name>
    <person>
        <![CDATA[122233344550]]>
        <![CDATA[122233344551]]>
        <![CDATA[]]>
        <name><some>Jack</some>Jack</name>
        <name><some>Mohan</some></name>
        <blank></blank>
        <regx>^[ ].*$</regx>
    </person>
</any_name>

It is recommended to use preserveOrder: true when parsing XML to a JS object and building it back, so that CDATA order is maintained.

Note: If value contains CDATA start/end delimiters then the builder will automatically santize the value.


commentPropName

Identifies properties whose values should be rendered as XML comments (<!-- ... -->).

Example input:

{
    "any_name": {
        "person": {
            "phone": [122233344550, 122233344551, ""],
            "name": ["<some>Jack</some>Jack", "<some>Mohan</some>"],
            "blank": "",
            "regx": "^[ ].*$"
        }
    }
}

Code:

const options = {
    processEntities: false,
    format: true,
    ignoreAttributes: false,
    commentPropName: "phone"
};
const builder = new XMLBuilder(options);
const xmlOutput = builder.build(input);

Output:

<any_name>
    <person>
        <!--122233344550-->
        <!--122233344551-->
        <!---->
        <name><some>Jack</some>Jack</name>
        <name><some>Mohan</some></name>
        <blank></blank>
        <regx>^[ ].*$</regx>
    </person>
</any_name>

It is recommended to use preserveOrder: true when parsing XML to a JS object and building it back, so that comment order is maintained.

Note: If value contains comment start/end delimiters then the builder will automatically santize the value.


format

By default, output is a single-line XML string. Set format: true to produce indented, human-readable XML.


ignoreAttributes

By default (true), the builder skips all attributes. Set to false to include them.

You can also selectively ignore specific attributes using an array of strings, an array of regular expressions, or a callback function.

Example input

{
    "tag": {
        "$ns:attr1": "a1-value",
        "$ns:attr2": "a2-value",
        "$ns2:attr3": "a3-value",
        "$ns2:attr4": "a4-value",
        "tag2": {
            "$ns:attr1": "a1-value",
            "$ns:attr2": "a2-value",
            "$ns2:attr3": "a3-value",
            "$ns2:attr4": "a4-value"
        }
    }
}

Ignore by array of strings

const options = {
    attributeNamePrefix: "$",
    ignoreAttributes: ['ns:attr1', 'ns:attr2']
};
<tag ns2:attr3="a3-value" ns2:attr4="a4-value">
    <tag2 ns2:attr3="a3-value" ns2:attr4="a4-value"></tag2>
</tag>

Ignore by array of regular expressions

const options = {
    attributeNamePrefix: "$",
    ignoreAttributes: [/^ns2:/]
};
<tag ns:attr1="a1-value" ns:attr2="a2-value">
    <tag2 ns:attr1="a1-value" ns:attr2="a2-value"></tag2>
</tag>

indentBy

The string used for each indentation level. Default: ' ' (two spaces). Only applies when format: true.


maxNestedTags

Limits the maximum depth of nested tags. An error is thrown if the nesting depth exceeds this value. Default: 100.

const options = { maxNestedTags: 10 };
const builder = new XMLBuilder(options);
const xmlOutput = builder.build(jsonData);

oneListGroup

Groups all repeated child tags under a single parent tag.

Input:

{
    "Attributes": [
        { "Attribute": "1" },
        { "Attribute": "2" }
    ]
}

Code:

const builder = new XMLBuilder({ oneListGroup: true });
const output = builder.build(json);

Output:

<Attributes>
    <Attribute>1</Attribute>
    <Attribute>2</Attribute>
</Attributes>

preserveOrder

When you parse XML using Fast XML Parser with preserveOrder: true or Flexible-XML-parser with Sequential Builder, the result has a different structure. Pass preserveOrder:true to get the same XML response back.


processEntities

Set to true (default) to replace special characters with XML entities (&amp;, &lt;, &gt;, &apos;, &quot;). Disable with processEntities: false for better performance when you know your content contains no entities.

Security note: Single and double quotes in attribute values are always escaped to &apos; and &quot;, regardless of this setting.


sanitizeName

Callback function that transforms tag or attribute names. Receives the raw name and returns the sanitized version.

const builder = new XMLBuilder({
    sanitizeName: (name) => "_" + name
});

By default it is set to false. This means, builder will not santize the tag and attribute names.

Please note that we use xml-entities to validate tag and attribute names. This also consider xml version given in XML declaration. However, if not present then default version considered is 1.0.


stopNodes

Tags listed here are treated as raw content containers. Their text content is written as-is without entity encoding or child processing.

Accepts an array of tag name strings or pre-compiled Expression instances from path-expression-matcher.

The old *.tagName wildcard syntax is still accepted and is automatically converted to the equivalent ..tagName deep-wildcard expression.

This option is currently only supported with preserveOrder: true.

A stop node may have raw content and attributes, but is not expected to have child nodes, CDATA, comments, or other structured properties.

Example (with preserveOrder: true):

[{
    root: [
        { foo: [{ '#text': '<p>raw html</p>' }] },
        { bar: [{ '#text': '' }] }
    ]
}]

suppressBooleanAttributes

When true (default), attributes whose value is true are rendered as boolean attributes (value omitted).

Input:

const jsOrderedObj = [
    {
        "?textinfo": [{ "#text": "" }],
        ":@": {
            "@_whitespace": true,
            "@_is": true,
            "@_allowed": true
        }
    }
];
const options = {
    ignoreAttributes: false,
    preserveOrder: true,
    allowBooleanAttributes: true,
    suppressBooleanAttributes: true
};
const builder = new XMLBuilder(options);
const output = builder.build(jsOrderedObj);

Output:

<?textinfo whitespace is allowed?>

suppressEmptyNode

When true, tags with no text value are rendered as self-closing tags.

Input:

const builder = new XMLBuilder({ suppressEmptyNode: true });
const output = builder.build({ a: 32, b: "" });

Output:

<a>32</a>
<b/>

suppressUnpairedNode

Controls the rendering of unpaired tags. Default: true.

  • true (default): renders as <br> (no closing slash)
  • false: renders as <br/>

tagValueProcessor

Customize how tag text values are serialized. Receives the tag name and its raw value.

const options = {
    tagValueProcessor: (tagName, val) => val.trim()
};

Note: For stop nodes, tagValueProcessor is skipped and values are written as-is.


textNodeName

The property name used to represent the text content of a tag in the JS object. Default: '#text'.


unpairedTags

A list of tag names that have no closing tag (e.g. <br>, <img> in HTML). You can provide the same list to the parser, validator, and builder.

Example:

const options = { unpairedTags: ["br", "img"] };
const builder = new XMLBuilder(options);

Restoring original XML

Example 1 — alwaysCreateTextNode

const XMLdata = `<car>
  <color>purple</color>
  <type>minivan</type>
</car>`;

const parser = new XMLParser({ alwaysCreateTextNode: true });
let result = parser.parse(XMLdata);

const builder = new XMLBuilder({ format: true });
const output = builder.build(result);

Output:

<car>
  <color>purple</color>
  <type>minivan</type>
</car>

Example 2 — isArray

const parser = new XMLParser({
    isArray: (tagName, jPath, isLeafNode) => isLeafNode
});
let result = parser.parse(XMLdata);

const builder = new XMLBuilder();
const output = builder.build(result);

Example 3 — preserveOrder

const parser = new XMLParser({ preserveOrder: true });
let result = parser.parse(XMLdata);

const builder = new XMLBuilder({ preserveOrder: true });
const output = builder.build(result);

Example 4 — Matching attributeNamePrefix

Always set attributeNamePrefix and other shared options to the same value in both the parser and builder.

const options = {
    ignoreAttributes: false,
    attributeNamePrefix: "@@",
    format: true
};
const parser = new XMLParser(options);
let result = parser.parse(XMLdata);

const builder = new XMLBuilder(options);
const output = builder.build(result);

Round-tripping XML → JSON → XML (XML declaration)

If your input XML contains a declaration like <?xml version="1.0"?>, the fast-xml-parser may include it in the output JSON as a "?xml" property (unless disabled).
When converting the JSON back to XML, you may want to omit this node to avoid invalid output (e.g., “XML declaration allowed only at the start of the document”).

Option A (recommended): ignore the declaration while parsing*

import { XMLParser, XMLBuilder } from "fast-xml-parser";

const parser = new XMLParser({ ignoreDeclaration: true });
const builder = new XMLBuilder();

const obj = parser.parse(xmlInput);
const xmlOutput = builder.build(obj);

Option B: Remove the XML declaration node before building

If you need to preserve the XML declaration during parsing but want to prevent it from being re-emitted during JSON → XML conversion, you can remove the "?xml" node before building:

import { XMLParser, XMLBuilder } from "fast-xml-parser";

const parser = new XMLParser();
const builder = new XMLBuilder();

const obj = parser.parse(xmlInput);

// Remove XML declaration before building
delete obj["?xml"];

const xmlOutput = builder.build(obj);