Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/strophe/strophejs/llms.txt

Use this file to discover all available pages before exploring further.

The Builder class is Strophe.js’s primary tool for constructing XMPP stanzas programmatically. It provides a fluent, chainable interface — similar to jQuery — for building XML trees without manually juggling DOM APIs. Every method that mutates the tree returns the Builder instance itself (or a child-focused instance), so you can compose complex stanzas in a single expression. Four shorthand factory functions ($build, $msg, $iq, $pres) cover the most common cases and save you from calling new Builder(...) directly.

Shorthand Helper Functions

These module-level functions are the recommended way to start building stanzas. They are exported directly from strophe.js and also registered on globalThis for environments that prefer global access.
$msg, $iq, and $pres automatically inject xmlns='jabber:client' on the root element if no xmlns attribute is provided. This matches the XMPP client-stream namespace and is required for well-formed client stanzas.

$build

$build(name: string, attrs?: StanzaAttrs): Builder
Creates a new Builder rooted at an element with the given tag name. Use this for arbitrary element names that don’t match the three core XMPP stanza types.
name
string
required
The tag name of the root element (e.g. "iq", "message", "stream:features").
attrs
StanzaAttrs
Optional attributes for the root element, expressed as a plain object where keys are attribute names and values are string or number.
import { $build } from 'strophe.js';

const elem = $build('stream:features').tree();

$msg

$msg(attrs?: Record<string, string>): Builder
Creates a Builder rooted at a <message/> element. The xmlns='jabber:client' attribute is added automatically when not supplied.
attrs
Record<string, string>
Optional attributes for the <message/> element (e.g. to, from, type, id).
import { $msg } from 'strophe.js';

const stanza = $msg({ to: 'alice@example.org', type: 'chat' })
    .c('body').t('Hello, Alice!').up()
    .toString();
// <message to="alice@example.org" type="chat" xmlns="jabber:client">
//   <body>Hello, Alice!</body>
// </message>

$iq

$iq(attrs?: Record<string, string>): Builder
Creates a Builder rooted at an <iq/> element. The xmlns='jabber:client' attribute is added automatically when not supplied.
attrs
Record<string, string>
Optional attributes for the <iq/> element (e.g. to, type, id).
import { $iq } from 'strophe.js';

const stanza = $iq({ to: 'example.org', type: 'get', id: '1' })
    .c('query', { xmlns: 'jabber:iq:roster' })
    .toString();
// <iq id="1" to="example.org" type="get" xmlns="jabber:client">
//   <query xmlns="jabber:iq:roster"/>
// </iq>

$pres

$pres(attrs?: Record<string, string>): Builder
Creates a Builder rooted at a <presence/> element. The xmlns='jabber:client' attribute is added automatically when not supplied.
attrs
Record<string, string>
Optional attributes for the <presence/> element (e.g. from, type).
import { $pres } from 'strophe.js';

const stanza = $pres({ from: 'juliet@example.com/chamber' })
    .c('show').t('away').up()
    .c('status').t('Be right back').up()
    .toString();
// <presence from="juliet@example.com/chamber" xmlns="jabber:client">
//   <show>away</show>
//   <status>Be right back</status>
// </presence>

Builder Class

The Builder class implements the underlying chainable XML-construction engine. You can instantiate it directly, but in practice the shorthand helpers above are more ergonomic for the standard stanza types.

Type: StanzaAttrs

type StanzaAttrs = Record<string, string | number>
Attribute maps used by the constructor and $build. Values may be string or number; numbers are coerced to strings when applied to the DOM.

Constructor

new Builder(name: string, attrs?: StanzaAttrs)
Constructs a new Builder and prepares the root element. The element is created lazily — DOM construction is deferred until tree() or toString() is first called.
name
string
required
Tag name of the root element.
attrs
StanzaAttrs
Attributes to apply to the root element. When name is "message", "iq", or "presence" and no xmlns key is present, xmlns='jabber:client' is injected automatically.
import Builder from 'strophe.js';

const b = new Builder('message', { to: 'you', from: 'me' });
const b2 = new Builder('message', { 'xml:lang': 'en' });

Instance Methods

tree()

tree(): Element
Returns the root DOM Element of the stanza being built. This is the object you pass to connection.send(). Calling tree() does not reset the internal “current node” cursor — subsequent chained calls continue from wherever the cursor was.
returns
Element
The root DOM element of the XML tree.
const elem: Element = $iq({ type: 'get', id: '2' })
    .c('ping', { xmlns: 'urn:ietf:params:xml:ns:xmpp-ping' })
    .tree(); // returns the root <iq/> Element

connection.send(elem);

toString()

toString(): string
Serializes the entire XML tree to a string. Attribute names are sorted alphabetically in the output. Special characters in attribute values and text nodes are XML-escaped automatically.
returns
string
The complete XML serialization of the stanza tree.
const xml = $msg({ to: 'bob@example.org', type: 'chat' })
    .c('body').t('Hi Bob')
    .toString();

console.log(xml);
// <message to="bob@example.org" type="chat" xmlns="jabber:client">
//   <body>Hi Bob</body>
// </message>

up()

up(): Builder
Moves the current-element pointer up one level to the parent of the current node. This is the primary mechanism for adding multiple children to the same parent in a single chain.
returns
Builder
The same Builder instance, with the cursor now pointing at the parent element.
If you need to jump all the way back to the root rather than stepping up one level at a time, use root() instead.
// Add two sibling children, then serialize from the root
const stanza = $msg({ to: 'alice@example.org', type: 'chat' })
    .c('body').t('Hello!').up()
    .c('active', { xmlns: 'http://jabber.org/protocol/chatstates' })
    .tree();

root()

root(): Builder
Moves the current-element pointer all the way back to the root of the tree. When you are deeply nested after a series of c() calls, root() is more convenient than calling up() repeatedly.
returns
Builder
The same Builder instance, with the cursor reset to the root element.
// Build a deeply nested tree, then jump back to root in one call
const stanza = $iq({ type: 'set', id: '5' })
    .c('query', { xmlns: 'jabber:iq:roster' })
        .c('item', { jid: 'bob@example.org' })
            .c('group').t('Friends')
    .root()           // cursor is now back on <iq/>
    .toString();

attrs(moreattrs)

attrs(moreattrs: Record<string, string | number | null>): Builder
Adds new attributes to, or modifies existing attributes on, the current element. Does not move the cursor. Setting a value to null or undefined removes the attribute entirely.
moreattrs
Record<string, string | number | null>
required
An object of attribute names to new values. Pass null to remove an attribute.
returns
Builder
The same Builder instance.
$iq({ type: 'get', id: 'temp' })
    .attrs({ id: 'final-id', 'xml:lang': 'en' }) // update id, add xml:lang
    .attrs({ 'xml:lang': null })                   // remove xml:lang again
    .toString();

c(name, attrs?, text?)

c(name: string, attrs?: Record<string, string> | string, text?: string): Builder
Appends a new child element to the current node and moves the cursor down to that child, making it the new current element. If text is provided, a text node is added inside the child and the cursor stays on the child.
name
string
required
Tag name of the new child element.
attrs
Record<string, string> | string
Attributes for the child element as an object, or a shorthand string value.
text
string
Optional text content to add inside the child. When provided, the cursor does not descend into the child.
returns
Builder
The same Builder instance, with the cursor now on the newly created child (unless text was supplied).
Because c() moves the cursor to the child, calling another c() immediately after nests a grandchild. Use up() to return to the parent before adding a sibling.
// Nested children
$iq({ to: 'example.org', type: 'set', id: '3' })
    .c('query', { xmlns: 'jabber:iq:roster' })
        .c('item', { jid: 'bob@example.org', name: 'Bob', subscription: 'both' })
    .toString();

cnode(elem)

cnode(elem: Element | Builder): Builder
Appends an existing DOM Element or another Builder as a child of the current node, then moves the cursor to that child. The element is deep-copied (or imported) before appending, so the original is not mutated.
elem
Element | Builder
required
An existing DOM element or Builder instance to graft into the tree.
returns
Builder
The same Builder instance, with the cursor on the appended child.
const itemElem = $build('item', { jid: 'carol@example.org' }).tree();

$iq({ type: 'set', id: '4' })
    .c('query', { xmlns: 'jabber:iq:roster' })
    .cnode(itemElem)
    .toString();

t(text)

t(text: string): Builder
Appends a text node to the current element. The cursor does not move — there are no children to descend into from a text node. The text is stored as-is in the DOM; XML-escaping happens automatically during serialization.
text
string
required
The text content to append.
returns
Builder
The same Builder instance.
$msg({ to: 'dave@example.org', type: 'chat' })
    .c('body')
    .t('Plain text content here')
    .up()
    .toString();

h(html)

h(html: string): Builder
Replaces the current element’s content with parsed XHTML. The HTML string is first parsed into a DOM fragment, then filtered through Strophe’s XHTML-IM allow-list before being appended — unsafe tags and attributes are stripped automatically.
html
string
required
An HTML string whose safe subset will be inserted as child nodes of the current element.
returns
Builder
The same Builder instance.
Only elements and attributes permitted by the XHTML-IM profile (XEP-0071) survive the filter. Do not rely on h() to preserve arbitrary HTML markup.
$msg({ to: 'eve@example.org', type: 'chat' })
    .c('html', { xmlns: 'http://jabber.org/protocol/xhtml-im' })
    .c('body', { xmlns: 'http://www.w3.org/1999/xhtml' })
    .h('<p>Hello, <strong>Eve</strong>!</p>')
    .toString();

Static Methods

Builder.fromString(str)

static fromString(str: string): Builder
Parses a raw XML string into a Builder, allowing you to use the fluent API on top of a stanza you received or constructed externally.
str
string
required
A well-formed XML string to parse. A parse error will be thrown if the string is invalid.
returns
Builder
A new Builder instance wrapping the parsed element.
const b = Builder.fromString('<presence from="juliet@example.com/chamber"></presence>');
b.c('show').t('dnd');
console.log(b.toString());
// <presence from="juliet@example.com/chamber"><show>dnd</show></presence>

Builder.serialize(elem)

static serialize(elem: Element | Builder | null): string | null
Serializes a DOM Element or Builder to an XML string. Returns null when elem is null. This is the same serialization logic used internally by toString(). Attribute names are sorted; text content and attribute values are XML-escaped.
elem
Element | Builder | null
required
The element or builder to serialize.
returns
string | null
The serialized XML string, or null if elem was null.
import Builder from 'strophe.js';

const el: Element = document.createElementNS('jabber:client', 'message');
el.setAttribute('to', 'frank@example.org');

const xml: string | null = Builder.serialize(el);
// '<message to="frank@example.org"/>'

Chaining Examples

Complex IQ roster query

import { $iq } from 'strophe.js';

$iq({ to: 'example.org', type: 'get', id: '1' })
    .c('query', { xmlns: 'jabber:iq:roster' })
    .toString();
// <iq id="1" to="example.org" type="get" xmlns="jabber:client">
//   <query xmlns="jabber:iq:roster"/>
// </iq>

Multi-child message with chat-state notification

import { $msg } from 'strophe.js';

const elem = $msg({ to: 'alice@example.org', type: 'chat' })
    .c('body').t('Hello!').up()
    .c('active', { xmlns: 'http://jabber.org/protocol/chatstates' })
    .tree();

connection.send(elem);

Building a roster item set

import { $iq } from 'strophe.js';

$iq({ type: 'set', id: 'roster-1' })
    .c('query', { xmlns: 'jabber:iq:roster' })
        .c('item', { jid: 'romeo@example.net', name: 'Romeo', subscription: 'both' })
            .c('group').t('Friends').up()
        .up()
    .up()
    .toString();

Build docs developers (and LLMs) love