# HG changeset patch # User Kim Alvefur # Date 1660755870 -7200 # Node ID e8934ce6ea0f47fcc9265dc7896a31797ceeb0cf # Parent f928cb5c5d04a9795c0a3d6d3ec3ca1d18029c6a util.stanza: Add method for extracting a single attribute value Sometimes you only care about a single attribute, but the child tag itself may be optional, leading to needing `tag and tag.attr.foo` or `stanza:find("tag@foo")`. The `:find()` method is fairly complex, so avoiding it for this kind of simpler use case is a win. diff -r f928cb5c5d04 -r e8934ce6ea0f plugins/mod_pubsub/pubsub.lib.lua --- a/plugins/mod_pubsub/pubsub.lib.lua Mon Aug 15 16:35:14 2022 +0200 +++ b/plugins/mod_pubsub/pubsub.lib.lua Wed Aug 17 19:04:30 2022 +0200 @@ -678,8 +678,7 @@ function handlers.set_retract(origin, stanza, retract, service) local node, notify = retract.attr.node, retract.attr.notify; notify = (notify == "1") or (notify == "true"); - local item = retract:get_child("item"); - local id = item and item.attr.id + local id = retract:get_child_attr("item", nil, "id"); if not (node and id) then origin.send(pubsub_error_reply(stanza, node and "item-not-found" or "nodeid-required")); return true; diff -r f928cb5c5d04 -r e8934ce6ea0f spec/util_dataforms_spec.lua --- a/spec/util_dataforms_spec.lua Mon Aug 15 16:35:14 2022 +0200 +++ b/spec/util_dataforms_spec.lua Wed Aug 17 19:04:30 2022 +0200 @@ -130,7 +130,7 @@ assert.truthy(st.is_stanza(xform)); assert.equal("x", xform.name); assert.equal("jabber:x:data", xform.attr.xmlns); - assert.equal("FORM_TYPE", xform:find("field@var")); + assert.equal("FORM_TYPE", xform:get_child_attr("field", nil, "var")); assert.equal("xmpp:prosody.im/spec/util.dataforms#1", xform:find("field/value#")); local allowed_direct_children = { title = true, diff -r f928cb5c5d04 -r e8934ce6ea0f util/stanza.lua --- a/util/stanza.lua Mon Aug 15 16:35:14 2022 +0200 +++ b/util/stanza.lua Wed Aug 17 19:04:30 2022 +0200 @@ -176,6 +176,14 @@ return nil; end +function stanza_mt:get_child_attr(name, xmlns, attr) + local tag = self:get_child(name, xmlns); + if tag then + return tag.attr[attr]; + end + return nil; +end + function stanza_mt:child_with_name(name) for _, child in ipairs(self.tags) do if child.name == name then return child; end