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.

In XMPP, a stanza is a discrete XML element exchanged between a client and a server. The three core stanza types defined by the protocol are <message> (for chat and notifications), <iq> (Info/Query — for request/response interactions), and <presence> (for availability broadcasts). Custom extension elements can be nested inside any of these. Strophe.js provides two complementary APIs for constructing stanzas: the fluent Builder class and the stx tagged template literal introduced in 3.1.0.

The Builder Class

Builder provides a jQuery-inspired fluent interface for constructing XML trees programmatically. Each method (except tree() and toString()) returns the Builder instance so calls can be chained. The internal cursor tracks which element new children will be appended to — c() moves the cursor down, up() moves it back to the parent.

Shorthand Factory Functions

Four convenience functions create pre-configured Builder instances. These are available as named exports and as globals ($build, $msg, $iq, $pres) when using the UMD bundle:
import { $build, $msg, $iq, $pres } from 'strophejs';
FunctionRoot elementAuto-namespace
$build(name, attrs?)Any element nameNone
$msg(attrs?)<message>jabber:client
$iq(attrs?)<iq>jabber:client
$pres(attrs?)<presence>jabber:client
$msg, $iq, and $pres automatically inject xmlns="jabber:client" when no xmlns attribute is supplied. This ensures stanzas are valid according to RFC 6120 without requiring you to remember the namespace on every call.

Builder Methods

.c(name, attrs?, text?)
Builder
Append a child element and move the cursor to it. If text is provided, a text node is added and the cursor stays on the parent (convenient for single-line leaf nodes).
.cnode(elem)
Builder
Append an existing DOM Element (or another Builder) as a child and move the cursor to it. The element is imported/copied into the current document.
.t(text)
Builder
Append a text node to the current element. Does not move the cursor.
.h(html)
Builder
Replace the current element’s content with an XHTML-filtered version of the provided HTML string (for XEP-0071 XHTML-IM payloads).
.up()
Builder
Move the cursor back to the parent element.
.root()
Builder
Move the cursor directly back to the root element, regardless of nesting depth.
.attrs(moreAttrs)
Builder
Add or modify attributes on the current element. Pass null as a value to remove an attribute. Does not move the cursor.
.tree()
Element
Return the root DOM Element. Required when passing the stanza to conn.send() directly (though send() also accepts Builder objects).
.toString()
string
Serialize the entire XML tree to a string.

Building Stanzas with the Builder API

import { $msg } from 'strophejs';

// <message to="bob@example.com" type="chat" xmlns="jabber:client">
//   <body>Hello, Bob!</body>
// </message>
const msg = $msg({ to: 'bob@example.com', type: 'chat' })
  .c('body')
  .t('Hello, Bob!');

conn.send(msg);

Traversal and Multiple Children

When you need to add two siblings, call .up() after the first child to return the cursor to the parent before adding the second:
import { $msg } from 'strophejs';

// <message to="bob@example.com" type="chat" xmlns="jabber:client">
//   <body>Hi</body>
//   <active xmlns="http://jabber.org/protocol/chatstates"/>
// </message>
const msg = $msg({ to: 'bob@example.com', type: 'chat' })
  .c('body').t('Hi').up()
  .c('active', { xmlns: 'http://jabber.org/protocol/chatstates' });

The stx Tagged Template Literal

stx is an ES2015 tagged template function that lets you write stanzas as inline XML strings. Interpolated values are automatically XML-escaped, preventing injection attacks when you embed user-supplied data into stanza text content.
import { stx } from 'strophejs';

const to = 'bob@example.com';
const body = '<Hello & welcome!>'; // unsafe characters — will be escaped

const msg = stx`
  <message to="${to}" type="chat" xmlns="jabber:client">
    <body>${body}</body>
  </message>`;

conn.send(msg);
// Sends: <body>&lt;Hello &amp; welcome!&gt;</body>
Automatic escaping applies to string interpolations only. The template literal skeleton (the parts you type directly) is treated as raw XML and is not escaped. Never concatenate untrusted input into the template literal skeleton itself.

Interpolating Other Builders and Stanzas

stx accepts other Builder and Stanza instances as interpolated values. When a Builder is interpolated it is serialized in-place, without escaping:
import { stx, $build } from 'strophejs';

const show = $build('show').t('dnd');

const pres = stx`
  <presence from="juliet@example.com/chamber" xmlns="jabber:client">
    ${show}
    <status>Do not disturb</status>
  </presence>`;

conn.send(pres);

Stanza.unsafeXML() — Bypassing Escaping

When you have a pre-serialized XML fragment that you want to embed without escaping, wrap it in Stanza.unsafeXML():
import { stx, Stanza } from 'strophejs';

const rawXml = '<status>I am &amp; available</status>';

const pres = stx`
  <presence xmlns="jabber:client">
    ${Stanza.unsafeXML(rawXml)}
  </presence>`;
Only use unsafeXML with strings you fully control. Never pass user input through unsafeXML.

Equivalent Examples: Builder vs stx

import { $msg } from 'strophejs';

const msg = $msg({ to: 'bob@example.com', type: 'chat' })
  .c('body').t('Hello!');

conn.send(msg);
import { $iq } from 'strophejs';

const iq = $iq({ type: 'get', id: 'disco-1', to: 'conference.example.com' })
  .c('query', { xmlns: 'http://jabber.org/protocol/disco#info' });

conn.sendIQ(iq, onResult);

Parsing XML Strings into Elements

The toStanza() utility (an alias for Stanza.toElement()) parses an XML string into a DOM Element. It validates that message, iq, and presence elements carry a valid namespace (jabber:client or jabber:server):
import { toStanza } from 'strophejs';

const elem = toStanza(
  '<message from="alice@example.com" to="bob@example.com" type="chat" xmlns="jabber:client">' +
  '  <body>Hi</body>' +
  '</message>'
);

// elem is a standard DOM Element
console.log(elem.nodeName); // "message"
You can also use the static Builder.fromString() method to get a Builder wrapping a parsed element, enabling further chaining:
import { Builder } from 'strophejs';

const b = Builder.fromString('<iq type="get" xmlns="jabber:client"/>');
b.c('query', { xmlns: 'jabber:iq:roster' });
conn.send(b);

Build docs developers (and LLMs) love