util.stanza
The stanza module provides several methods for building and manipulating stanza objects.
Utility functions
Stanza construction
All of these functions create and return a new stanza object, on which you can call various methods, and which you may convert to a string of XML at any time with tostring(mystanza).
stanza(name, attr)
Creates a new stanza, with the specified name and attributes (attributes are standard key→value tables).
message(attr, body)
Helper for creating message stanzas, equivalent to stanza("message", attr), or stanza("message", attr):body(body) with the second argument.
presence(attr)
Helper for creating presence stanzas, equivalent to stanza("presence", attr).
iq(attr)
Helper for creating iq stanzas, equivalent to stanza("iq", attr).
reply(stanza)
Creates a 'reply' stanza. Replies are the same kind of stanza, with the to/from switched accordingly, and with the same id. If the stanza is an iq stanza, the reply's 'type' attribute will be 'result', otherwise it will be the same type as the original stanza.
error_reply(stanza, error_type, error_condition, error_text, error_by)
Constructs and returns an appropriate error reply to the given stanza. As reply() above, but the 'type' attribute is always 'error'.
error_type
must be one of: 'auth', 'cancel', 'continue',
'modify', 'wait' (see descriptions in RFC
6120)
error_condition
must be a valid XMPP error condition, as
in RFC
6120 Defined Error Conditions.
error_text
is optional, and may be set to a
human-readable text description of the error.
error_by
can be set to specify the JID that originates
the error when this differs from the to
of the original
stanza.
clone(stanza)
Return a clone of the given stanza, useful to hold on to copies of stanzas that may be modified by other plugins in Prosody.
Serialization
These functions are for preparing stanzas for storage, not for converted them to XML. For that see tostring(stanza).
preserialize(stanza)
Returns a version of the stanza that is suitable for serialization, e.g. through our storage API or util.serialization. You must call deserialize() below on the stanza before using it, when you read it back.
deserialize(stanza)
Make a full stanza object out of a previously serialized stanza.
Stanza objects
Properties
name
The name of the top tag of this object.
attr
A table of attributes for this object.
Numeric indexes
Every stanza object is itself an array of its child nodes, with strings for text nodes and stanza objects for child tags. Iterating over the children should be done using the children() method.
Methods
Stanza construction
These functions are used for adding content to stanza objects. For a full example of building a stanza from scratch, see Building a stanza.
stanza:tag(name, attr)
Inserts a child tag with the specified name and attributes to the stanza.
Calls can be chained, for example:
local my_message = stanza.message({to = "myfriend@example.com", type = "chat" })
:tag("body"):text("Hello there!")
print(my_message)
would produce:
message to='myfriend@example.com' type='chat'>
<body>Hello there!</body>
<message> </
stanza:text(text)
Inserts a text node.
stanza:text_tag(name, text, attr)
Convenience method equivalent to stanza:tag(name, attr):text(text):up()
Available starting with 0.12.0.
stanza:up()
Moves "up" in the node tree, so that the next child node may be added as a sibling instead of child node.
.message():tag("subject"):text("hi")
stanza:tag("body"):text("hello there")
--> <message><subject>hi<body>hello there</body></subject></message>
.message():tag("subject"):text("hi"):up()
stanza:tag("body"):text("hello there")
--> <message><subject>hi</subject><body>hello there</body></message>
stanza:body(text)
Convenience function for inserting a body
tag with the
specified text content to the stanza. Equivalent to
stanza:tag("body"):text(text):up()
So, in the above example, the stanza could also be constructed like this:
.message({ to = "myfriend@example.com", type = "chat" }):body("Hello there!") stanza
stanza:add_child(child)
Adds a child element (created with stanza() for example) to the current position in the stanza. See stanza:add_direct_child() to add to the element you call the method on, rather than at the current position under it.
stanza:reset()
Moves the 'context' position of the stanza object back to the top, so that stanza:tag() and other methods will work on the topmost element of the stanza. To return only a single level up, see stanza:up().
stanza:add_direct_child(child)
Similar to stanza:add_child(), but adds a child to the stanza element directly, ignoring (and not changing) the current position (so that :tag() and other methods will continue from where they were).
stanza:add_error(error_type, condition, error_message, error_by)
Adds a
<error type="{error_type}" by="{error_by}><{condition} xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/><text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">{error_message}</text></error>
child element at the current cursor position.
error_type
may be a string or a table. If it is a
string, its value is used directly for the type
attribute.
If it is a table, it should be the only argument and it is assumed to
originate from util.error
. The other
arguments are sourced from error_type
as follows:
error_type.type
is used aserror_type
error_type.condition
is used ascondition
error_type.text
is used aserror_message
error_type.context.by
(if present and a string) overrideserror_by
error_type.extra.uri
(if present and a string) is used as a text inside the<gone/>
element ifcondition
is equal togone
.error_type.extra.tag
(if present and a stanza) is added as a sibling child besides the condition and the text.
If error_type.extra.namespace
and
error_type.extra.condition
are both set and
error_type.extra.tag
is not set, then a sibling
element is generated using the condition as local name and the given
namespace.
If error_by
(after the above substitutions) is nil or
equal to the stanza’s from
attribute, the by
attribute is omitted.
If error_message
(after the above substitutions) is nil,
the <text/>
child is omitted.
stanza:query(xmlns)
Convenience function for inserting a query
tag with the
specified xmlns to the stanza.
.iq({ type = "get", to = "example.com" }):query("jabber:iq:version") stanza
Iteration
stanza:children()
Returns an iterator for all the object's immediate children, which are either of type "string" (text nodes) or "table" (child tags, also valid stanza objects).
The iterator can be used with Lua's generic 'for' loop like so:
for childnode in mystanza:children() do
print(childnode)
end
Querying stanzas
stanza:get_child(name, xmlns)
Retrieves the first child tag that matches the given name and xmlns. If xmlns is nil or not given then it defaults to the current stanza object's xmlns.
= stanza.message({ xmlns = "jabber:client" })
message :tag("body"):text("Hello world"):up()
:tag("delay", { xmlns = "urn:xmpp:delay", stamp = "2002-09-10T23:08:25Z" })
print("Body is:", message:get_child("body"):get_text())
print("Timestamp is:", message:get_child("delay", "urn:xmpp:delay").attr.stamp)
Returns nil if no matching tags are found.
stanza:child_with_name(name)
Returns the first child with the specified name. Warning: this method ignores namespaces, and may be deprecated in future versions. It is recommended to use stanza:get_child() instead.
stanza:child_with_ns(namespace)
Returns the first child with the specified namespace.
stanza:get_text()
Returns the text context of the current stanza.
stanza:get_child_text(name, xmlns)
Returns the text content of the first child tag matching name and xmlns (works like get_child() above), or nil if there's no such child.
stanza:get_child_with_attr()
Added in 0.12
:get_child_with_attr(name, xmlns, attr_name, attr_value, normalize) stanza
Returns a the first child tag with a matching attribute.
For example, given a message
like:
message type="chat">
<delay xmlns="urn:xmpp:delay" from="capulet.com" stamp="2002-09-10T23:08:25Z"/>
<delay xmlns="urn:xmpp:delay" from="montague.net" stamp="2002-09-10T23:08:29Z"/>
<message> </
Then the second <delay>
element can be reached
by:
local montague_delay = message:get_child_with_attr("delay", "urn:xmpp:delay", "from", "montague.net");
The normalize
argument takes a callback used to
normalize the attribute value for comparison, e.g. to enable case
insensitive comparison or similar.
stanza:get_child_attr(name, xmlns, attr_name)
Added in trunk
Retrieves a single attribute value from the first child tag that matches the given name and xmlns.
stanza:get_error()
Extracts and returns three values from an error stanza; the error type (e.g. 'auth'), the error condition (e.g. 'service-unavailable') and the error text (if any).
stanza:find(path)
This is a stanza query method similar to XPath, but a lot more simplistic. It only supports extracting a single child, attribute or text node. Its main purpose is to replace long chains of stanza:get_child(name, xmlns), without worrying about missing nodes causing errors.
The path is built of /-separated segments each representing an element, selected by either an XML namespace or an element name or both. The XML namespace is wrapped in { }. The final component can be prefixed with an @ character to return an attribute, or be a single # character to return the text content of the matching element.
Examples:
:find"{urn:xmpp:delay}delay@stamp" -- The timestamp of a XEP-0203 element.
stanza
:find"{http://jabber.org/protocol/disco#info}query/identity" -- <identity/> element of a info query.
stanza
:find"{http://jabber.org/protocol/pubsub#event}event/items/item/{http://www.w3.org/2005/Atom}entry/title#"
stanza--The title text of an Atom entry in a PubSub event.
Modifying stanzas
XML strings
tostring(stanza)
Return the stanza as a string of XML.
stanza:top_tag()
Returns the top tag of the stanza as a string.
stanza:pretty_print()
Like tostring(stanza)
, but uses ANSI colour escape
sequences to highlight the stanza.
stanza:pretty_top_tag()
As above, but returns only the top tag.
stanza:indent()
Returns a clone of the stanza with whitespace inserted between tags to produce indentation, making the structure easier to see for humans. Any existing whitespace only text nodes are replaced.
Added in 0.12
Examples
Building a stanza
This example XML (taken from XEP-0092):
iq
< type='result'
to='romeo@montague.net/orchard'
from='juliet@capulet.com/balcony'
id='version_1'>
query xmlns='jabber:iq:version'>
<name>Prosody</name>
<version>0.8.2</version>
<os>Ubuntu</os>
<query>
</iq> </
Would be expressed in Lua as:
.iq({ type = "result", to = "romeo@montague.net/orchard", from = "juliet@capulet.com/balcony", id = "version_1" })
stanza:tag("query", { xmlns = "jabber:iq:version" })
:tag("name"):text("Prosody"):up()
:tag("version"):text("0.8.2"):up()
:tag("os"):text("Ubuntu"):up()
We also have a small command-line Lua script for converting any given XML to its Lua counterpart. It reads in XML and prints out the equivalent Lua representation. You can download it here, and simply run it with 'lua stanzaconv.lua'.