124 lines
4.6 KiB
C++
124 lines
4.6 KiB
C++
#include "opdsparser.h"
|
|
|
|
#include <QStringList>
|
|
#include <QVariantMap>
|
|
#include <QXmlStreamReader>
|
|
|
|
static QString elementText(QXmlStreamReader &reader)
|
|
{
|
|
return reader.readElementText(QXmlStreamReader::IncludeChildElements).trimmed();
|
|
}
|
|
|
|
static QVariantMap parseEntry(QXmlStreamReader &reader)
|
|
{
|
|
QVariantMap entry;
|
|
QStringList authors;
|
|
QVariantList formats;
|
|
QString title;
|
|
QString summary;
|
|
QString id;
|
|
QString coverHref;
|
|
QString thumbHref;
|
|
QString navHref;
|
|
|
|
while (!reader.atEnd()) {
|
|
reader.readNext();
|
|
if (reader.tokenType() == QXmlStreamReader::EndElement
|
|
&& reader.name() == QLatin1String("entry"))
|
|
break;
|
|
if (reader.tokenType() != QXmlStreamReader::StartElement)
|
|
continue;
|
|
|
|
const QStringRef name = reader.name();
|
|
if (name == QLatin1String("title")) {
|
|
title = elementText(reader);
|
|
} else if (name == QLatin1String("id")) {
|
|
id = elementText(reader);
|
|
} else if (name == QLatin1String("name")) {
|
|
const QString author = elementText(reader);
|
|
if (!author.isEmpty())
|
|
authors.append(author);
|
|
} else if (name == QLatin1String("content") || name == QLatin1String("summary")) {
|
|
if (summary.isEmpty())
|
|
summary = elementText(reader);
|
|
} else if (name == QLatin1String("link")) {
|
|
const QXmlStreamAttributes attrs = reader.attributes();
|
|
const QString rel = attrs.value(QLatin1String("rel")).toString();
|
|
const QString href = attrs.value(QLatin1String("href")).toString();
|
|
const QString type = attrs.value(QLatin1String("type")).toString();
|
|
|
|
if (rel == QLatin1String("http://opds-spec.org/image")) {
|
|
coverHref = href;
|
|
} else if (rel == QLatin1String("http://opds-spec.org/image/thumbnail")) {
|
|
thumbHref = href;
|
|
} else if (rel == QLatin1String("http://opds-spec.org/acquisition")) {
|
|
QVariantMap format;
|
|
format.insert(QStringLiteral("format"), attrs.value(QLatin1String("title")).toString());
|
|
format.insert(QStringLiteral("mime"), type);
|
|
format.insert(QStringLiteral("size"), attrs.value(QLatin1String("length")).toString().toLongLong());
|
|
format.insert(QStringLiteral("url"), href);
|
|
formats.append(format);
|
|
} else if (rel == QLatin1String("subsection")) {
|
|
if (navHref.isEmpty())
|
|
navHref = href;
|
|
} else if (navHref.isEmpty() && type.contains(QLatin1String("opds-catalog"))) {
|
|
// calibre-web: i link di navigazione dell'indice non hanno rel="subsection"
|
|
navHref = href;
|
|
}
|
|
}
|
|
}
|
|
|
|
entry.insert(QStringLiteral("title"), title);
|
|
entry.insert(QStringLiteral("authors"), authors.join(QStringLiteral(", ")));
|
|
entry.insert(QStringLiteral("summary"), summary);
|
|
entry.insert(QStringLiteral("coverUrl"), !coverHref.isEmpty() ? coverHref : thumbHref);
|
|
entry.insert(QStringLiteral("formats"), formats);
|
|
entry.insert(QStringLiteral("id"), id);
|
|
entry.insert(QStringLiteral("isNavigation"), !navHref.isEmpty());
|
|
entry.insert(QStringLiteral("linkUrl"), navHref);
|
|
return entry;
|
|
}
|
|
|
|
bool OpdsParser::parse(const QByteArray &xml,
|
|
QVariantList *entries,
|
|
QString *nextUrl,
|
|
QString *feedTitle,
|
|
QString *errorMessage)
|
|
{
|
|
QXmlStreamReader reader(xml);
|
|
QVariantList result;
|
|
QString next;
|
|
QString title;
|
|
|
|
while (!reader.atEnd()) {
|
|
reader.readNext();
|
|
if (reader.tokenType() != QXmlStreamReader::StartElement)
|
|
continue;
|
|
|
|
const QStringRef name = reader.name();
|
|
if (name == QLatin1String("entry")) {
|
|
result.append(parseEntry(reader));
|
|
} else if (name == QLatin1String("link")) {
|
|
const QXmlStreamAttributes attrs = reader.attributes();
|
|
if (attrs.value(QLatin1String("rel")).toString() == QLatin1String("next"))
|
|
next = attrs.value(QLatin1String("href")).toString();
|
|
} else if (name == QLatin1String("title") && title.isEmpty()) {
|
|
title = elementText(reader);
|
|
}
|
|
}
|
|
|
|
if (reader.hasError() && result.isEmpty()) {
|
|
if (errorMessage)
|
|
*errorMessage = reader.errorString();
|
|
return false;
|
|
}
|
|
|
|
if (entries)
|
|
*entries = result;
|
|
if (nextUrl)
|
|
*nextUrl = next;
|
|
if (feedTitle)
|
|
*feedTitle = title;
|
|
return true;
|
|
}
|