syndication/atom
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 "constants.h" 00025 #include "content.h" 00026 #include "document.h" 00027 00028 #include <documentsource.h> 00029 00030 #include <QtXml/QDomAttr> 00031 #include <QtXml/QDomDocument> 00032 #include <QtXml/QDomElement> 00033 #include <QtXml/QDomNamedNodeMap> 00034 #include <QtXml/QDomNode> 00035 #include <QtXml/QDomNodeList> 00036 00037 #include <QtCore/QHash> 00038 #include <QtCore/QRegExp> 00039 #include <QtCore/QString> 00040 00041 namespace Syndication { 00042 namespace Atom { 00043 00044 class Parser::ParserPrivate 00045 { 00046 public: 00047 static QDomDocument convertAtom0_3(const QDomDocument& document); 00048 static QDomNode convertNode(QDomDocument& doc, const QDomNode& node, const QHash<QString, QString>& nameMapper); 00049 }; 00050 00051 bool Parser::accept(const Syndication::DocumentSource& source) const 00052 { 00053 QDomElement root = source.asDomDocument().documentElement(); 00054 return !root.isNull() && (root.namespaceURI() == atom1Namespace() || root.namespaceURI() == atom0_3Namespace()); 00055 } 00056 00057 Syndication::SpecificDocumentPtr Parser::parse(const Syndication::DocumentSource& source) const 00058 { 00059 QDomDocument doc = source.asDomDocument(); 00060 00061 if (doc.isNull()) 00062 { 00063 // if this is not atom, return an invalid feed document 00064 return FeedDocumentPtr(new FeedDocument()); 00065 } 00066 00067 QDomElement feed = doc.namedItem(QLatin1String("feed")).toElement(); 00068 00069 bool feedValid = !feed.isNull(); 00070 00071 if (feedValid && feed.attribute(QLatin1String("version")) 00072 == QLatin1String("0.3")) 00073 { 00074 doc = ParserPrivate::convertAtom0_3(doc); 00075 feed = doc.namedItem(QLatin1String("feed")).toElement(); 00076 00077 } 00078 00079 feedValid = !feed.isNull() && feed.namespaceURI() == atom1Namespace(); 00080 00081 if (feedValid) 00082 { 00083 return FeedDocumentPtr(new FeedDocument(feed)); 00084 } 00085 00086 QDomElement entry = doc.namedItem(QLatin1String("entry")).toElement(); 00087 bool entryValid = !entry.isNull() && entry.namespaceURI() == atom1Namespace(); 00088 00089 if (entryValid) 00090 { 00091 return EntryDocumentPtr(new EntryDocument(feed)); 00092 } 00093 00094 // if this is not atom, return an invalid feed document 00095 return FeedDocumentPtr(new FeedDocument()); 00096 } 00097 00098 QString Parser::format() const 00099 { 00100 return QLatin1String("atom"); 00101 } 00102 00103 QDomNode Parser::ParserPrivate::convertNode(QDomDocument& doc, const QDomNode& node, const QHash<QString, QString>& nameMapper) 00104 { 00105 if (!node.isElement()) 00106 return node.cloneNode(true); 00107 00108 bool isAtom03Element = node.namespaceURI() == atom0_3Namespace(); 00109 QDomElement oldEl = node.toElement(); 00110 00111 // use new namespace 00112 QString newNS = isAtom03Element ? atom1Namespace() : node.namespaceURI(); 00113 00114 QString newName = node.localName(); 00115 00116 // rename tags that are listed in the nameMapper 00117 if (isAtom03Element && nameMapper.contains(node.localName())) 00118 newName = nameMapper[node.localName()]; 00119 00120 QDomElement newEl = doc.createElementNS(newNS, newName); 00121 00122 QDomNamedNodeMap attributes = oldEl.attributes(); 00123 00124 // copy over attributes 00125 for (int i = 0; i < attributes.count(); ++i) 00126 { 00127 QDomAttr attr = attributes.item(i).toAttr(); 00128 if (attr.namespaceURI().isEmpty()) 00129 newEl.setAttribute(attr.name(), attr.value()); 00130 else 00131 newEl.setAttributeNS(attr.namespaceURI(), attr.name(), attr.value()); 00132 } 00133 00134 bool isTextConstruct = newNS == atom1Namespace() 00135 && (newName == QLatin1String("title") 00136 || newName == QLatin1String("rights") 00137 || newName == QLatin1String("subtitle") 00138 || newName == QLatin1String("summary")); 00139 00140 // for atom text constructs, map to new type schema (which only allows text, type, xhtml) 00141 00142 if (isTextConstruct) 00143 { 00144 QString oldType = newEl.attribute(QLatin1String("type"), QLatin1String("text/plain") ); 00145 QString newType; 00146 00147 Content::Format format = Content::mapTypeToFormat(oldType); 00148 switch (format) 00149 { 00150 case Content::XML: 00151 newType = QLatin1String("xhtml"); 00152 break; 00153 case Content::EscapedHTML: 00154 newType = QLatin1String("html"); 00155 break; 00156 case Content::PlainText: 00157 case Content::Binary: 00158 default: 00159 newType = QLatin1String("text"); 00160 00161 } 00162 00163 newEl.setAttribute(QLatin1String("type"), newType); 00164 } 00165 else 00166 { 00167 // for generator, rename the "url" attribute to "uri" 00168 00169 bool isGenerator = newNS == atom1Namespace() && newName == QLatin1String("generator"); 00170 if (isGenerator && newEl.hasAttribute(QLatin1String("url"))) 00171 newEl.setAttribute(QLatin1String("uri"), newEl.attribute(QLatin1String("url"))); 00172 } 00173 00174 // process child nodes recursively and append them 00175 QDomNodeList children = node.childNodes(); 00176 for (int i = 0; i < children.count(); ++i) 00177 { 00178 newEl.appendChild(convertNode(doc, children.item(i), nameMapper)); 00179 } 00180 00181 return newEl; 00182 } 00183 00184 QDomDocument Parser::ParserPrivate::convertAtom0_3(const QDomDocument& doc03) 00185 { 00186 QDomDocument doc = doc03.cloneNode(false).toDocument(); 00187 00188 // these are the tags that were renamed in 1.0 00189 QHash<QString, QString> nameMapper; 00190 nameMapper.insert(QLatin1String("issued"), QLatin1String("published")); 00191 nameMapper.insert(QLatin1String("modified"), QLatin1String("updated")); 00192 nameMapper.insert(QLatin1String("url"), QLatin1String("uri")); 00193 nameMapper.insert(QLatin1String("copyright"), QLatin1String("rights")); 00194 nameMapper.insert(QLatin1String("tagline"), QLatin1String("subtitle")); 00195 00196 QDomNodeList children = doc03.childNodes(); 00197 00198 for (int i = 0; i < children.count(); ++i) 00199 { 00200 doc.appendChild(convertNode(doc, children.item(i), nameMapper)); 00201 } 00202 00203 return doc; 00204 } 00205 00206 Parser::Parser() : d(0) {} 00207 Parser::~Parser() {} 00208 Parser::Parser(const Parser& other) : AbstractParser(other), d(0) {} 00209 Parser& Parser::operator=(const Parser& /*other*/) { return *this; } 00210 00211 } // namespace Atom 00212 } // namespace Syndication
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu Aug 2 2012 15:24:51 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu Aug 2 2012 15:24:51 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.