#include "opdsparser.h" #include #include #include 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; }