2
* xmlcommon.cpp - helper functions for dealing with XML
3
* Copyright (C) 2001, 2002 Justin Karneges
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
#include "xmpp_xmlcommon.h"
22
#include "xmpp_stanza.h"
26
#include <qdatetime.h>
29
#include <qstringlist.h>
32
//----------------------------------------------------------------------------
34
//----------------------------------------------------------------------------
35
XDomNodeList::XDomNodeList()
39
XDomNodeList::XDomNodeList(const XDomNodeList &from) :
44
XDomNodeList::XDomNodeList(const QDomNodeList &from)
46
for(int n = 0; n < from.count(); ++n)
50
XDomNodeList::~XDomNodeList()
54
XDomNodeList & XDomNodeList::operator=(const XDomNodeList &from)
60
bool XDomNodeList::isEmpty() const
62
return list.isEmpty();
65
QDomNode XDomNodeList::item(int index) const
67
return list.value(index);
70
uint XDomNodeList::length() const
72
return (uint)list.count();
75
bool XDomNodeList::operator==(const XDomNodeList &a) const
77
return (list == a.list);
80
void XDomNodeList::append(const QDomNode &i)
86
QDateTime stamp2TS(const QString &ts)
91
int year = ts.mid(0,4).toInt();
92
int month = ts.mid(4,2).toInt();
93
int day = ts.mid(6,2).toInt();
95
int hour = ts.mid(9,2).toInt();
96
int min = ts.mid(12,2).toInt();
97
int sec = ts.mid(15,2).toInt();
100
xd.setYMD(year, month, day);
105
xt.setHMS(hour, min, sec);
109
return QDateTime(xd, xt);
112
bool stamp2TS(const QString &ts, QDateTime *d)
114
QDateTime dateTime = stamp2TS(ts);
115
if (dateTime.isNull())
123
QString TS2stamp(const QDateTime &d)
127
str.sprintf("%04d%02d%02dT%02d:%02d:%02d",
138
QDomElement textTag(QDomDocument *doc, const QString &name, const QString &content)
140
QDomElement tag = doc->createElement(name);
141
QDomText text = doc->createTextNode(content);
142
tag.appendChild(text);
147
QString tagContent(const QDomElement &e)
149
// look for some tag content
150
for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
151
QDomText i = n.toText();
162
* \brief find an direct child element by name
163
* \param e parent element
164
* \param name name of element to find
165
* \param found (optional/out) found?
166
* \return the element (or a null QDomElemnt if not found)
168
QDomElement findSubTag(const QDomElement &e, const QString &name, bool *found)
173
for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
174
QDomElement i = n.toElement();
177
if(i.tagName() == name) {
190
* \brief obtain direct child elements of a certain kind. unlike
191
* elementsByTagNameNS, this function does not descend beyond the first
193
* \param e parent element
194
* \param nsURI namespace of the elements to find
195
* \param localName local name of the elements to find
196
* \return the node list of found elements (empty list if none are found)
198
XDomNodeList childElementsByTagNameNS(const QDomElement &e, const QString &nsURI, const QString &localName)
201
for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
204
QDomElement i = n.toElement();
205
if(i.namespaceURI() == nsURI && i.localName() == localName)
213
* \brief create a new IQ stanza
216
* \param to destination jid
217
* \param id stanza id
218
* \return the created stanza
220
QDomElement createIQ(QDomDocument *doc, const QString &type, const QString &to, const QString &id)
222
QDomElement iq = doc->createElement("iq");
224
iq.setAttribute("type", type);
226
iq.setAttribute("to", to);
228
iq.setAttribute("id", id);
233
/** \brief returns direct child element named "query"
234
* \return the element (or a null QDomElemnt if not found)
236
QDomElement queryTag(const QDomElement &e)
239
QDomElement q = findSubTag(e, "query", &found);
243
QString queryNS(const QDomElement &e)
246
QDomElement q = findSubTag(e, "query", &found);
248
return q.attribute("xmlns");
254
\brief Extracts the error code and description from the stanza element.
256
This function finds the error element in the given stanza element \a e.
258
You need to provide the base namespace of the stream to which this stanza belongs to
259
(probably by using stream.baseNS() function).
261
The error description is either error text extracted from XML
262
or - if no text is found - the error name and description (separated by '\n') taken from RFC-3920
263
or - if the error is not defined in the RFC - the empty string.
265
Note: This function uses the Stanza::Error class,
266
so it may guess missing values as defined in JEP-0086.
268
\param e the element representing stanza
269
\param baseNS the base namespace of the stream
270
\param code if not NULL, will be filled with numeric error code
271
\param str if not NULL, will be filled with human readable error description
274
void getErrorFromElement(const QDomElement &e, const QString &baseNS, int *code, QString *str)
277
QDomElement tag = findSubTag(e, "error", &found);
281
XMPP::Stanza::Error err;
282
err.fromXml(tag, baseNS);
287
QPair<QString, QString> desc = err.description();
288
if (err.text.isEmpty())
289
*str = desc.first + ".\n" + desc.second;
291
*str = desc.first + ".\n" + desc.second + "\n" + err.text;
296
QDomElement addCorrectNS(const QDomElement &e)
301
/*QDomDocumentFragment frag = e.ownerDocument().createDocumentFragment();
302
QDomNodeList nl = e.childNodes();
303
for(x = 0; x < nl.count(); ++x)
304
frag.appendChild(nl.item(x).cloneNode());*/
306
// find closest xmlns
308
while(!n.isNull() && !n.toElement().hasAttribute("xmlns"))
311
if(n.isNull() || !n.toElement().hasAttribute("xmlns"))
312
ns = "jabber:client";
314
ns = n.toElement().attribute("xmlns");
317
QDomElement i = e.ownerDocument().createElementNS(ns, e.tagName());
320
QDomNamedNodeMap al = e.attributes();
321
for(x = 0; x < al.count(); ++x) {
322
QDomAttr a = al.item(x).toAttr();
323
if(a.name() != "xmlns")
324
i.setAttributeNodeNS(a.cloneNode().toAttr());
328
QDomNodeList nl = e.childNodes();
329
for(x = 0; x < nl.count(); ++x) {
330
QDomNode n = nl.item(x);
332
i.appendChild(addCorrectNS(n.toElement()));
334
i.appendChild(n.cloneNode());
337
//i.appendChild(frag);
341
//----------------------------------------------------------------------------
343
//----------------------------------------------------------------------------
345
namespace XMLHelper {
347
QDomElement emptyTag(QDomDocument *doc, const QString &name)
349
QDomElement tag = doc->createElement(name);
354
bool hasSubTag(const QDomElement &e, const QString &name)
357
findSubTag(e, name, &found);
361
QString subTagText(const QDomElement &e, const QString &name)
364
QDomElement i = findSubTag(e, name, &found);
367
return QString::null;
370
QDomElement textTag(QDomDocument &doc, const QString &name, const QString &content)
372
QDomElement tag = doc.createElement(name);
373
QDomText text = doc.createTextNode(content);
374
tag.appendChild(text);
379
QDomElement textTag(QDomDocument &doc, const QString &name, int content)
381
QDomElement tag = doc.createElement(name);
382
QDomText text = doc.createTextNode(QString::number(content));
383
tag.appendChild(text);
388
QDomElement textTag(QDomDocument &doc, const QString &name, bool content)
390
QDomElement tag = doc.createElement(name);
391
QDomText text = doc.createTextNode(content ? "true" : "false");
392
tag.appendChild(text);
397
QDomElement textTag(QDomDocument &doc, const QString &name, QSize &s)
400
str.sprintf("%d,%d", s.width(), s.height());
402
QDomElement tag = doc.createElement(name);
403
QDomText text = doc.createTextNode(str);
404
tag.appendChild(text);
409
QDomElement textTag(QDomDocument &doc, const QString &name, QRect &r)
412
str.sprintf("%d,%d,%d,%d", r.x(), r.y(), r.width(), r.height());
414
QDomElement tag = doc.createElement(name);
415
QDomText text = doc.createTextNode(str);
416
tag.appendChild(text);
421
QDomElement stringListToXml(QDomDocument &doc, const QString &name, const QStringList &l)
423
QDomElement tag = doc.createElement(name);
424
for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it)
425
tag.appendChild(textTag(doc, "item", *it));
430
/*QString tagContent(const QDomElement &e)
432
// look for some tag content
433
for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
434
QDomText i = n.toText();
443
/*QDomElement findSubTag(const QDomElement &e, const QString &name, bool *found)
448
for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
449
QDomElement i = n.toElement();
452
if(i.tagName() == name) {
463
void readEntry(const QDomElement &e, const QString &name, QString *v)
466
QDomElement tag = findSubTag(e, name, &found);
469
*v = tagContent(tag);
472
void readNumEntry(const QDomElement &e, const QString &name, int *v)
475
QDomElement tag = findSubTag(e, name, &found);
478
*v = tagContent(tag).toInt();
481
void readBoolEntry(const QDomElement &e, const QString &name, bool *v)
484
QDomElement tag = findSubTag(e, name, &found);
487
*v = (tagContent(tag) == "true") ? TRUE: FALSE;
490
void readSizeEntry(const QDomElement &e, const QString &name, QSize *v)
493
QDomElement tag = findSubTag(e, name, &found);
496
QStringList list = tagContent(tag).split(',');
497
if(list.count() != 2)
500
s.setWidth(list[0].toInt());
501
s.setHeight(list[1].toInt());
505
void readRectEntry(const QDomElement &e, const QString &name, QRect *v)
508
QDomElement tag = findSubTag(e, name, &found);
511
QStringList list = tagContent(tag).split(',');
512
if(list.count() != 4)
515
r.setX(list[0].toInt());
516
r.setY(list[1].toInt());
517
r.setWidth(list[2].toInt());
518
r.setHeight(list[3].toInt());
522
void readColorEntry(const QDomElement &e, const QString &name, QColor *v)
525
QDomElement tag = findSubTag(e, name, &found);
529
c.setNamedColor(tagContent(tag));
534
void xmlToStringList(const QDomElement &e, const QString &name, QStringList *v)
537
QDomElement tag = findSubTag(e, name, &found);
541
for(QDomNode n = tag.firstChild(); !n.isNull(); n = n.nextSibling()) {
542
QDomElement i = n.toElement();
545
if(i.tagName() == "item")
546
list += tagContent(i);
551
void setBoolAttribute(QDomElement e, const QString &name, bool b)
553
e.setAttribute(name, b ? "true" : "false");
556
void readBoolAttribute(QDomElement e, const QString &name, bool *v)
558
if(e.hasAttribute(name)) {
559
QString s = e.attribute(name);
560
*v = (s == "true") ? TRUE: FALSE;