268 end |
268 end |
269 self = self:get_child(name, xmlns); |
269 self = self:get_child(name, xmlns); |
270 until not self |
270 until not self |
271 end |
271 end |
272 |
272 |
|
273 local function _clone(stanza, only_top) |
|
274 local attr, tags = {}, {}; |
|
275 for k,v in pairs(stanza.attr) do attr[k] = v; end |
|
276 local old_namespaces, namespaces = stanza.namespaces; |
|
277 if old_namespaces then |
|
278 namespaces = {}; |
|
279 for k,v in pairs(old_namespaces) do namespaces[k] = v; end |
|
280 end |
|
281 local new = { name = stanza.name, attr = attr, namespaces = namespaces, tags = tags }; |
|
282 if not only_top then |
|
283 for i=1,#stanza do |
|
284 local child = stanza[i]; |
|
285 if child.name then |
|
286 child = _clone(child); |
|
287 t_insert(tags, child); |
|
288 end |
|
289 t_insert(new, child); |
|
290 end |
|
291 end |
|
292 return setmetatable(new, stanza_mt); |
|
293 end |
|
294 |
|
295 local function clone(stanza, only_top) |
|
296 if not is_stanza(stanza) then |
|
297 error("bad argument to clone: expected stanza, got "..type(stanza)); |
|
298 end |
|
299 return _clone(stanza, only_top); |
|
300 end |
273 |
301 |
274 local escape_table = { ["'"] = "'", ["\""] = """, ["<"] = "<", [">"] = ">", ["&"] = "&" }; |
302 local escape_table = { ["'"] = "'", ["\""] = """, ["<"] = "<", [">"] = ">", ["&"] = "&" }; |
275 local function xml_escape(str) return (s_gsub(str, "['&<>\"]", escape_table)); end |
303 local function xml_escape(str) return (s_gsub(str, "['&<>\"]", escape_table)); end |
276 |
304 |
277 local function _dostring(t, buf, self, _xml_escape, parentns) |
305 local function _dostring(t, buf, self, _xml_escape, parentns) |
308 _dostring(t, buf, _dostring, xml_escape, nil); |
336 _dostring(t, buf, _dostring, xml_escape, nil); |
309 return t_concat(buf); |
337 return t_concat(buf); |
310 end |
338 end |
311 |
339 |
312 function stanza_mt.top_tag(t) |
340 function stanza_mt.top_tag(t) |
313 local attr_string = ""; |
341 local top_tag_clone = clone(t, true); |
314 if t.attr then |
342 return tostring(top_tag_clone):sub(1,-3)..">"; |
315 for k, v in pairs(t.attr) do if type(k) == "string" then attr_string = attr_string .. s_format(" %s='%s'", k, xml_escape(tostring(v))); end end |
|
316 end |
|
317 return s_format("<%s%s>", t.name, attr_string); |
|
318 end |
343 end |
319 |
344 |
320 function stanza_mt.get_text(t) |
345 function stanza_mt.get_text(t) |
321 if #t.tags == 0 then |
346 if #t.tags == 0 then |
322 return t_concat(t); |
347 return t_concat(t); |
384 stanza:add_direct_child(child); |
409 stanza:add_direct_child(child); |
385 end |
410 end |
386 end |
411 end |
387 return stanza; |
412 return stanza; |
388 end |
413 end |
389 end |
|
390 |
|
391 local function _clone(stanza) |
|
392 local attr, tags = {}, {}; |
|
393 for k,v in pairs(stanza.attr) do attr[k] = v; end |
|
394 local old_namespaces, namespaces = stanza.namespaces; |
|
395 if old_namespaces then |
|
396 namespaces = {}; |
|
397 for k,v in pairs(old_namespaces) do namespaces[k] = v; end |
|
398 end |
|
399 local new = { name = stanza.name, attr = attr, namespaces = namespaces, tags = tags }; |
|
400 for i=1,#stanza do |
|
401 local child = stanza[i]; |
|
402 if child.name then |
|
403 child = _clone(child); |
|
404 t_insert(tags, child); |
|
405 end |
|
406 t_insert(new, child); |
|
407 end |
|
408 return setmetatable(new, stanza_mt); |
|
409 end |
|
410 |
|
411 local function clone(stanza) |
|
412 if not is_stanza(stanza) then |
|
413 error("bad argument to clone: expected stanza, got "..type(stanza)); |
|
414 end |
|
415 return _clone(stanza); |
|
416 end |
414 end |
417 |
415 |
418 local function message(attr, body) |
416 local function message(attr, body) |
419 if not body then |
417 if not body then |
420 return new_stanza("message", attr); |
418 return new_stanza("message", attr); |