xmlbuilder2
can convert JS objects into XML nodes. Each key/value pair of a JS object is converted into an element node, where object key becomes the node name and object value becomes the node contents.
const { create } = require('xmlbuilder');
const obj = {
root: 'text'
};
const doc = create().ele(obj);
console.log(doc.end({ prettyPrint: true }));
<?xml version="1.0"?>
<root>text</root>
If the object value is another JS object, it will be recursively converted into nodes.
const { create } = require('xmlbuilder');
const obj = {
root: {
foo: {
bar: 'foobar'
}
}
};
const doc = create().ele(obj);
console.log(doc.end({ prettyPrint: true }));
<?xml version="1.0"?>
<root>
<foo>
<bar>foobar</bar>
</foo>
</root>
If the object value is an array, each array item will be converted into a child node. In that case, name of the child nodes will be the object key.
const { create } = require('xmlbuilder');
const obj = {
root: {
child: [
'one',
'two',
'three'
]
}
};
const doc = create().ele(obj);
console.log(doc.end({ prettyPrint: true }));
<?xml version="1.0"?>
<root>
<child>one</child>
<child>two</child>
<child>three</child>
</root>
Although this allows element and text nodes to be easily created, a special syntax is needed for other types of nodes and element attributes. This special syntax is provided with converter strings. Default converter strings and their behavior are as follows.
Converter Strings
Converter strings can be customized with the convert
option while initializing the builder; see builder options.
att
Converts its key-value pair to an element attribute. Defaults to '@'
.
obj = { pilot: { '@callsign': 'Maverick', '@rank': 'Lieutenant' } }
will be converted into:
<pilot callsign="Maverick" rank="Lieutenant"/>
Note: An alternative notation is to group multiple attributes under the attribute key.
obj = { pilot: { '@': { 'callsign': 'Maverick', 'rank': 'Lieutenant' } } }
is also converted into:
<pilot callsign="Maverick" rank="Lieutenant"/>
ins
Converts its value to a processing instruction node. Defaults to '?'
. Instruction target and value should be separated with a single space character.
obj = {
'?': 'background classified ref="NAM#123456"',
pilot: 'Pete Mitchell'
}
becomes:
<?background classified ref="NAM#123456"?>
<pilot>Pete Mitchell</pilot>
text
Converts its value to a text node if it is a string, otherwise expands its value under its parent element node. Defaults to '#'
.
obj = { monologue: {
'#': 'Talk to me Goose!'
} }
becomes:
<monologue>Talk to me Goose!</monologue>
Note:
text
converter is usually not needed as object values are converted to text nodes
by default. So the above example is equivalent to:
obj = { monologue: 'Talk to me Goose!' }
<monologue>Talk to me Goose!</monologue>
text
converter is needed in advanced use cases as explained below.
Note: Since JS objects cannot contain duplicate keys, multiple text nodes can be created by adding some unique text after each object key or grouping node contents in an array. Example:
obj1 = { monologue: {
'#1': 'Talk to me Goose!',
'#2': 'Talk to me...'
} }
obj2 = { monologue: {
'#': [
'Talk to me Goose!',
'Talk to me...'
]
} }
both become:
<monologue>Talk to me Goose!Talk to me...</monologue>
Note:
'#'
also allows mixed content. Example:
obj1 = { monologue: {
'#1': 'Talk to me Goose!',
'cut': 'dog tag shot',
'#2': 'Talk to me...'
} }
obj2 = { monologue: {
'#': [
'Talk to me Goose!',
{ 'cut': 'dog tag shot' },
'Talk to me...'
]
} }
both become:
<monologue>
Talk to me Goose!
<cut>dog tag shot</cut>
Talk to me...
</monologue>
cdata
Converts its value to a CDATA section node. Defaults to '$'
.
obj = {
'$': '<a href="https://topgun.fandom.com/wiki/MiG-28"/>',
aircraft: 'MiG-28'
}
becomes:
<![CDATA[<a href="https://topgun.fandom.com/wiki/MiG-28"/>]]>
<aircraft>MiG-28</aircraft>
comment
Converts its value to a comment node. Defaults to '!'
.
obj = {
'!': 'Fictional; MiGs use odd numbers for fighters.',
aircraft: 'MiG-28'
}
becomes:
<!--Fictional; MiGs use odd numbers for fighters.-->
<aircraft>MiG-28</aircraft>
Namespaces
When converting JS objects, element and attribute namespaces can be specified as follows:
obj = {
'root@http://example.com/ns1': 'foo'
}
becomes:
<root xmlns="http://example.com/ns1">foo</root>