23 #include <rss2/document.h>
24 #include <rss2/category.h>
25 #include <rss2/cloud.h>
26 #include <rss2/image.h>
27 #include <rss2/item.h>
28 #include <rss2/textinput.h>
30 #include <constants.h>
31 #include <documentvisitor.h>
34 #include <QtXml/QDomDocument>
35 #include <QtCore/QList>
36 #include <QtCore/QSet>
37 #include <QtCore/QString>
39 namespace Syndication {
42 class Document::DocumentPrivate
45 DocumentPrivate() : itemDescriptionIsCDATA(false),
46 itemDescriptionContainsMarkup(false),
47 itemDescGuessed(false),
48 itemTitleIsCDATA(false),
49 itemTitleContainsMarkup(false),
50 itemTitlesGuessed(false)
52 mutable bool itemDescriptionIsCDATA;
53 mutable bool itemDescriptionContainsMarkup;
54 mutable bool itemDescGuessed;
55 mutable bool itemTitleIsCDATA;
56 mutable bool itemTitleContainsMarkup;
57 mutable bool itemTitlesGuessed;
60 Document::Document(
const QDomElement& element) : SpecificDocument(),
61 ElementWrapper(element),
62 d(new DocumentPrivate)
66 Document Document::fromXML(
const QDomDocument& doc)
68 QDomNode channelNode = doc.namedItem(QLatin1String(
"rss")).namedItem(QLatin1String(
"channel"));
70 return Document(channelNode.toElement());
73 Document::Document() : SpecificDocument(), ElementWrapper(), d(new DocumentPrivate)
77 Document::Document(
const Document& other) : SpecificDocument(other), ElementWrapper(other)
86 Document& Document::operator=(
const Document& other)
88 ElementWrapper::operator=(other);
92 bool Document::isValid()
const
97 QString Document::title()
const
99 return extractElementTextNS(QString(), QLatin1String(
"title"));
102 QString Document::link()
const
104 return extractElementTextNS(QString(), QLatin1String(
"link") );
107 QString Document::description()
const
109 QString desc = extractElementTextNS(QString(), QLatin1String(
"description"));
110 return normalize(desc);
113 QString Document::language()
const
115 QString lang = extractElementTextNS(QString(),
116 QLatin1String(
"language"));
124 return extractElementTextNS(
125 dublinCoreNamespace(), QLatin1String(
"language"));
130 QString Document::copyright()
const
132 QString rights = extractElementTextNS(QString(),
133 QLatin1String(
"copyright"));
134 if (!rights.isNull())
141 return extractElementTextNS(dublinCoreNamespace(),
142 QLatin1String(
"rights"));
146 QString Document::managingEditor()
const
148 return extractElementTextNS(QString(), QLatin1String(
"managingEditor"));
151 QString Document::webMaster()
const
153 return extractElementTextNS(QString(), QLatin1String(
"webMaster"));
156 time_t Document::pubDate()
const
158 QString str = extractElementTextNS(QString(), QLatin1String(
"pubDate"));
162 return parseDate(str, RFCDate);
166 str = extractElementTextNS(dublinCoreNamespace(), QLatin1String(
"date"));
167 return parseDate(str, ISODate);
171 time_t Document::lastBuildDate()
const
173 QString str = extractElementTextNS(QString(), QLatin1String(
"lastBuildDate"));
175 return parseDate(str, RFCDate);
178 QList<Category> Document::categories()
const
180 QList<Category> categories;
182 QList<QDomElement> catNodes = elementsByTagNameNS(QString(),
183 QLatin1String(
"category"));
184 QList<QDomElement>::ConstIterator it = catNodes.constBegin();
185 for ( ; it != catNodes.constEnd(); ++it)
187 categories.append(Category(*it));
193 QString Document::generator()
const
195 return extractElementTextNS(QString(), QLatin1String(
"generator"));
198 QString Document::docs()
const
200 return extractElementTextNS(QString(), QLatin1String(
"docs"));
203 Cloud Document::cloud()
const
205 return Cloud(firstElementByTagNameNS(QString(), QLatin1String(
"cloud")));
208 int Document::ttl()
const
213 QString text = extractElementTextNS(QString(), QLatin1String(
"ttl"));
218 Image Document::image()
const
220 return Image(firstElementByTagNameNS(QString(), QLatin1String(
"image")));
223 TextInput Document::textInput()
const
225 TextInput ti = TextInput(firstElementByTagNameNS(QString(), QLatin1String(
"textInput")));
231 return TextInput(firstElementByTagNameNS(QString(), QLatin1String(
"textinput")));
234 QSet<int> Document::skipHours()
const
237 QDomElement skipHoursNode = firstElementByTagNameNS(QString(),
238 QLatin1String(
"skipHours"));
239 if (!skipHoursNode.isNull())
241 ElementWrapper skipHoursWrapper(skipHoursNode);
243 QList<QDomElement> hours =
244 skipHoursWrapper.elementsByTagNameNS(QString(),
245 QLatin1String(
"hour"));
246 QList<QDomElement>::ConstIterator it = hours.constBegin();
247 for ( ; it != hours.constEnd(); ++it)
249 int h = (*it).text().toInt(&ok);
258 QSet<Document::DayOfWeek> Document::skipDays()
const
260 QSet<DayOfWeek> skipDays;
261 QDomElement skipDaysNode = firstElementByTagNameNS(QString(), QLatin1String(
"skipDays"));
262 if (!skipDaysNode.isNull())
264 ElementWrapper skipDaysWrapper(skipDaysNode);
265 QHash<QString, DayOfWeek> weekDays;
267 weekDays[QLatin1String(
"Monday")] = Monday;
268 weekDays[QLatin1String(
"Tuesday")] = Tuesday;
269 weekDays[QLatin1String(
"Wednesday")] = Wednesday;
270 weekDays[QLatin1String(
"Thursday")] = Thursday;
271 weekDays[QLatin1String(
"Friday")] = Friday;
272 weekDays[QLatin1String(
"Saturday")] = Saturday;
273 weekDays[QLatin1String(
"Sunday")] = Sunday;
275 QList<QDomElement> days = skipDaysWrapper.elementsByTagNameNS(QString(), QLatin1String(
"day"));
276 for (QList<QDomElement>::ConstIterator it = days.constBegin(); it != days.constEnd(); ++it)
278 if (weekDays.contains((*it).text()))
279 skipDays.insert(weekDays[(*it).text()]);
286 QList<Item> Document::items()
const
290 QList<QDomElement> itemNodes = elementsByTagNameNS(QString(), QLatin1String(
"item"));
292 DocumentPtr doccpy(
new Document(*
this));
294 for (QList<QDomElement>::ConstIterator it = itemNodes.constBegin(); it != itemNodes.constEnd(); ++it)
296 items.append(Item(*it, doccpy));
301 QList<QDomElement> Document::unhandledElements()
const
304 QList<ElementType> handled;
305 handled.append(ElementType(QLatin1String(
"title")));
306 handled.append(ElementType(QLatin1String(
"link")));
307 handled.append(ElementType(QLatin1String(
"description")));
308 handled.append(ElementType(QLatin1String(
"language")));
309 handled.append(ElementType(QLatin1String(
"copyright")));
310 handled.append(ElementType(QLatin1String(
"managingEditor")));
311 handled.append(ElementType(QLatin1String(
"webMaster")));
312 handled.append(ElementType(QLatin1String(
"pubDate")));
313 handled.append(ElementType(QLatin1String(
"lastBuildDate")));
314 handled.append(ElementType(QLatin1String(
"skipDays")));
315 handled.append(ElementType(QLatin1String(
"skipHours")));
316 handled.append(ElementType(QLatin1String(
"item")));
317 handled.append(ElementType(QLatin1String(
"textinput")));
318 handled.append(ElementType(QLatin1String(
"textInput")));
319 handled.append(ElementType(QLatin1String(
"image")));
320 handled.append(ElementType(QLatin1String(
"ttl")));
321 handled.append(ElementType(QLatin1String(
"generator")));
322 handled.append(ElementType(QLatin1String(
"docs")));
323 handled.append(ElementType(QLatin1String(
"cloud")));
324 handled.append(ElementType(QLatin1String(
"language"), dublinCoreNamespace()));
325 handled.append(ElementType(QLatin1String(
"rights"), dublinCoreNamespace()));
326 handled.append(ElementType(QLatin1String(
"date"), dublinCoreNamespace()));
328 QList<QDomElement> notHandled;
330 QDomNodeList children = element().childNodes();
331 for (
int i = 0; i < children.size(); ++i)
333 QDomElement el = children.at(i).toElement();
335 && !handled.contains(ElementType(el.localName(), el.namespaceURI())))
337 notHandled.append(el);
344 QString Document::debugInfo()
const
347 info += QLatin1String(
"### Document: ###################\n");
348 if (!title().isNull())
349 info += QLatin1String(
"title: #") + title() + QLatin1String(
"#\n");
350 if (!description().isNull())
351 info += QLatin1String(
"description: #") + description() + QLatin1String(
"#\n");
352 if (!link().isNull())
353 info += QLatin1String(
"link: #") + link() + QLatin1String(
"#\n");
354 if (!language().isNull())
355 info += QLatin1String(
"language: #") + language() + QLatin1String(
"#\n");
356 if (!copyright().isNull())
357 info += QLatin1String(
"copyright: #") + copyright() + QLatin1String(
"#\n");
358 if (!managingEditor().isNull())
359 info += QLatin1String(
"managingEditor: #") + managingEditor() + QLatin1String(
"#\n");
360 if (!webMaster().isNull())
361 info += QLatin1String(
"webMaster: #") + webMaster() + QLatin1String(
"#\n");
363 QString dpubdate = dateTimeToString(pubDate());
364 if (!dpubdate.isNull())
365 info += QLatin1String(
"pubDate: #") + dpubdate + QLatin1String(
"#\n");
367 QString dlastbuilddate = dateTimeToString(lastBuildDate());
368 if (!dlastbuilddate.isNull())
369 info += QLatin1String(
"lastBuildDate: #") + dlastbuilddate + QLatin1String(
"#\n");
371 if (!textInput().isNull())
372 info += textInput().debugInfo();
373 if (!cloud().isNull())
374 info += cloud().debugInfo();
375 if (!image().isNull())
376 info += image().debugInfo();
378 QList<Category> cats = categories();
380 for (QList<Category>::ConstIterator it = cats.constBegin(); it != cats.constEnd(); ++it)
381 info += (*it).debugInfo();
382 QList<Item> litems = items();
383 for (QList<Item>::ConstIterator it = litems.constBegin(); it != litems.constEnd(); ++it)
384 info += (*it).debugInfo();
385 info += QLatin1String(
"### Document end ################\n");
389 void Document::getItemTitleFormatInfo(
bool* isCDATA,
bool* containsMarkup)
const
391 if (!d->itemTitlesGuessed)
394 QList<Item> litems = items();
396 if (litems.isEmpty())
398 d->itemTitlesGuessed =
true;
402 QDomElement titleEl = (*litems.begin()).firstElementByTagNameNS(QString(), QLatin1String(
"title"));
403 d->itemTitleIsCDATA = titleEl.firstChild().isCDATASection();
405 int nmax = litems.size() < 10 ? litems.size() : 10;
408 QList<Item>::ConstIterator it = litems.constBegin();
412 titles += (*it).originalTitle();
417 d->itemTitleContainsMarkup = stringContainsMarkup(titles);
418 d->itemTitlesGuessed =
true;
422 *isCDATA = d->itemTitleIsCDATA;
423 if (containsMarkup != 0L)
424 *containsMarkup = d->itemTitleContainsMarkup;
427 void Document::getItemDescriptionFormatInfo(
bool* isCDATA,
bool* containsMarkup)
const
429 if (!d->itemDescGuessed)
432 QList<Item> litems = items();
435 if (litems.isEmpty())
437 d->itemDescGuessed =
true;
441 QDomElement descEl = (*litems.begin()).firstElementByTagNameNS(QString(), QLatin1String(
"description"));
442 d->itemDescriptionIsCDATA = descEl.firstChild().isCDATASection();
444 int nmax = litems.size() < 10 ? litems.size() : 10;
447 QList<Item>::ConstIterator it = litems.constBegin();
451 desc += (*it).originalDescription();
456 d->itemDescriptionContainsMarkup = stringContainsMarkup(desc);
457 d->itemDescGuessed =
true;
461 *isCDATA = d->itemDescriptionIsCDATA;
462 if (containsMarkup != 0L)
463 *containsMarkup = d->itemDescriptionContainsMarkup;
466 bool Document::accept(DocumentVisitor* visitor)
468 return visitor->visitRSS2Document(
this);