• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • KDE Home
  • Contact Us
 

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

syndication/atom

Skip menu "syndication/atom"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Members
  • File List

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal