syndication/rdf
parser.cpp
00001 /* 00002 * This file is part of the syndication library 00003 * 00004 * Copyright (C) 2006 Frank Osterfeld <osterfeld@kde.org> 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Library General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Library General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Library General Public License 00017 * along with this library; see the file COPYING.LIB. If not, write to 00018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 * 00021 */ 00022 00023 #include "parser.h" 00024 #include "document.h" 00025 #include "model.h" 00026 #include "modelmaker.h" 00027 #include "property.h" 00028 #include "rdfvocab.h" 00029 #include "resource.h" 00030 #include "rssvocab.h" 00031 #include "statement.h" 00032 00033 #include <documentsource.h> 00034 00035 #include <QtXml/QDomDocument> 00036 #include <QtXml/QDomNodeList> 00037 #include <QtCore/QHash> 00038 #include <QtCore/QList> 00039 #include <QtCore/QMap> 00040 #include <QtCore/QString> 00041 #include <QtCore/QStringList> 00042 00043 namespace Syndication { 00044 namespace RDF { 00045 00046 class Parser::ParserPrivate 00047 { 00048 public: 00049 QDomDocument addEnumeration(const QDomDocument& doc); 00050 void map09to10(Model model); 00051 void addSequenceFor09(Model model); 00052 00053 QString strInternalNs; 00054 QString strItemIndex; 00055 }; 00056 00057 bool Parser::accept(const DocumentSource& source) const 00058 { 00059 QDomDocument doc = source.asDomDocument(); 00060 00061 if (doc.isNull()) 00062 return false; 00063 QDomElement root = doc.documentElement(); 00064 00065 if (!root.isElement()) 00066 return false; 00067 00068 return root.namespaceURI() == RDFVocab::self()->namespaceURI(); 00069 } 00070 00071 SpecificDocumentPtr Parser::parse(const DocumentSource& source) const 00072 { 00073 QDomDocument doc = source.asDomDocument(); 00074 00075 if (doc.isNull()) 00076 return Syndication::SpecificDocumentPtr(new Document()); 00077 00078 doc = d->addEnumeration(doc); 00079 00080 ModelMaker maker; 00081 Model model = maker.createFromXML(doc); 00082 00083 bool is09 = !model.resourcesWithType(RSS09Vocab::self()->channel()).isEmpty(); 00084 00085 if (is09) 00086 { 00087 d->map09to10(model); 00088 d->addSequenceFor09(model); 00089 } 00090 00091 QList<ResourcePtr> channels = model.resourcesWithType(RSSVocab::self()->channel()); 00092 00093 if (channels.isEmpty()) 00094 return Syndication::SpecificDocumentPtr(new Document()); 00095 00096 return DocumentPtr(new Document(*(channels.begin()))); 00097 } 00098 00099 QDomDocument Parser::ParserPrivate::addEnumeration(const QDomDocument& docp) 00100 { 00101 QDomDocument doc(docp); 00102 00103 QDomNodeList list = doc.elementsByTagNameNS(RSS09Vocab::self()->namespaceURI(), 00104 QLatin1String("item")); 00105 00106 for (int i = 0; i < list.size(); ++i) 00107 { 00108 QDomElement item = list.item(i).toElement(); 00109 if (!item.isNull()) 00110 { 00111 QDomElement ie = doc.createElementNS(strInternalNs, strItemIndex); 00112 item.appendChild(ie); 00113 ie.appendChild(doc.createTextNode(QString::number(i))); 00114 00115 } 00116 } 00117 00118 return doc; 00119 } 00120 00121 void Parser::ParserPrivate::map09to10(Model model) 00122 { 00123 QHash<QString, PropertyPtr> hash; 00124 00125 hash.insert(RSS09Vocab::self()->title()->uri(), RSSVocab::self()->title()); 00126 hash.insert(RSS09Vocab::self()->description()->uri(), RSSVocab::self()->description()); 00127 hash.insert(RSS09Vocab::self()->link()->uri(), RSSVocab::self()->link()); 00128 hash.insert(RSS09Vocab::self()->name()->uri(), RSSVocab::self()->name()); 00129 hash.insert(RSS09Vocab::self()->url()->uri(), RSSVocab::self()->url()); 00130 hash.insert(RSS09Vocab::self()->image()->uri(), RSSVocab::self()->image()); 00131 hash.insert(RSS09Vocab::self()->textinput()->uri(), RSSVocab::self()->textinput()); 00132 00133 QStringList uris09 = RSS09Vocab::self()->properties(); 00134 00135 // map statement predicates to RSS 1.0 00136 00137 QList<StatementPtr> statements = model.statements(); 00138 QList<StatementPtr>::ConstIterator it = statements.constBegin(); 00139 QList<StatementPtr>::ConstIterator end = statements.constEnd(); 00140 00141 for ( ; it != end; ++it) 00142 { 00143 StatementPtr stmt = *it; 00144 00145 QString predUri = stmt->predicate()->uri(); 00146 if (uris09.contains(predUri)) 00147 { 00148 model.addStatement(stmt->subject(), hash[predUri], stmt->object()); 00149 } 00150 } 00151 // map channel type 00152 QList<ResourcePtr> channels = model.resourcesWithType(RSS09Vocab::self()->channel()); 00153 00154 ResourcePtr channel; 00155 00156 if (!channels.isEmpty()) 00157 { 00158 channel = *(channels.begin()); 00159 00160 model.removeStatement(channel, RDFVocab::self()->type(), RSS09Vocab::self()->channel()); 00161 model.addStatement(channel, RDFVocab::self()->type(), RSSVocab::self()->channel()); 00162 } 00163 } 00164 00165 void Parser::ParserPrivate::addSequenceFor09(Model model) 00166 { 00167 //RDF 0.9 doesn't contain an item sequence, and the items don't have rdf:about, so add both 00168 00169 const QList<ResourcePtr> items = model.resourcesWithType(RSS09Vocab::self()->item()); 00170 00171 if (items.isEmpty()) 00172 return; 00173 00174 const QList<ResourcePtr> channels = model.resourcesWithType(RSSVocab::self()->channel()); 00175 00176 if (channels.isEmpty()) 00177 return; 00178 00179 PropertyPtr itemIndex = model.createProperty(strInternalNs + strItemIndex); 00180 00181 // use QMap here, not QHash. as we need the sorting functionality 00182 QMap<uint, ResourcePtr> sorted; 00183 00184 foreach (const ResourcePtr &i, items) 00185 { 00186 QString numstr = i->property(itemIndex)->asString(); 00187 bool ok = false; 00188 uint num = numstr.toUInt(&ok); 00189 if (ok) 00190 { 00191 sorted[num] = i; 00192 } 00193 } 00194 00195 SequencePtr seq = model.createSequence(); 00196 model.addStatement(channels.first(), RSSVocab::self()->items(), seq); 00197 00198 foreach (const ResourcePtr &i, sorted) 00199 { 00200 seq->append(i); 00201 // add rdf:about (type) 00202 model.addStatement(i, RDFVocab::self()->type(), RSSVocab::self()->item()); 00203 00204 //add to items sequence 00205 model.addStatement(seq, RDFVocab::self()->li(), i); 00206 } 00207 } 00208 00209 Parser::Parser() : d(new ParserPrivate) 00210 { 00211 d->strInternalNs = QLatin1String("http://akregator.sf.net/libsyndication/internal#"); 00212 d->strItemIndex = QLatin1String("itemIndex"); 00213 } 00214 00215 Parser::~Parser() 00216 { 00217 delete d; 00218 } 00219 00220 Parser::Parser(const Parser& other) : AbstractParser(other), d(0) {} 00221 Parser& Parser::operator=(const Parser& /*other*/) { return *this; } 00222 00223 QString Parser::format() const 00224 { 00225 return QLatin1String("rdf"); 00226 } 00227 00228 00229 } // namespace RDF 00230 } // namespace Syndication
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon May 14 2012 04:47:16 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon May 14 2012 04:47:16 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.