Parcourir la source

Create class: Fb2XmlHandler

Kandrashin Denis il y a 13 ans
Parent
commit
138bcd2e3a
5 fichiers modifiés avec 165 ajouts et 134 suppressions
  1. 2 1
      source/fb2edit.pro
  2. 8 100
      source/fb2read.cpp
  3. 11 33
      source/fb2read.h
  4. 98 0
      source/fb2xml.cpp
  5. 46 0
      source/fb2xml.h

+ 2 - 1
source/fb2edit.pro

@@ -11,7 +11,8 @@ SOURCES = \
     fb2main.cpp \
     fb2read.cpp \
     fb2tree.cpp \
-    fb2view.cpp
+    fb2view.cpp \
+    fb2xml.cpp
 
 RESOURCES = \
     res/fb2edit.qrc

+ 8 - 100
source/fb2read.cpp

@@ -107,42 +107,6 @@ static QString Value(const QXmlAttributes &attributes, const QString &name)
     return QString();
 }
 
-Fb2ReadHandler::BaseHandler::~BaseHandler()
-{
-    if (m_handler) delete m_handler;
-}
-
-bool Fb2ReadHandler::BaseHandler::doStart(const QString &name, const QXmlAttributes &attributes)
-{
-    if (m_handler) return m_handler->doStart(name, attributes);
-    m_handler = NewTag(name, attributes); if (m_handler) return true;
-//    qCritical() << QObject::tr("Unknown XML child tag: <%1> <%2>").arg(m_name).arg(name);
-    m_handler = new BaseHandler(m_writer, name);
-    return true;
-}
-
-bool Fb2ReadHandler::BaseHandler::doText(const QString &text)
-{
-    if (m_handler) m_handler->doText(text); else TxtTag(text);
-    return true;
-}
-
-bool Fb2ReadHandler::BaseHandler::doEnd(const QString &name, bool & exists)
-{
-    if (m_handler) {
-        bool found = exists || name == m_name;
-        m_handler->doEnd(name, found);
-        if (m_handler->m_closed) { delete m_handler; m_handler = NULL; }
-        if (found) { exists = true; return true; }
-    }
-    bool found = name == m_name;
-    if (!found) qCritical() << QObject::tr("Conglict XML tags: <%1> - </%2>").arg(m_name).arg(name);
-    m_closed = found || exists;
-    if (m_closed) EndTag(m_name);
-    exists = found;
-    return true;
-}
-
 //---------------------------------------------------------------------------
 //  Fb2ReadHandler::RootHandler
 //---------------------------------------------------------------------------
@@ -161,7 +125,7 @@ Fb2ReadHandler::RootHandler::RootHandler(Fb2ReadWriter &writer, const QString &n
     m_writer.writeStartElement("body");
 }
 
-Fb2ReadHandler::BaseHandler * Fb2ReadHandler::RootHandler::NewTag(const QString &name, const QXmlAttributes &attributes)
+Fb2XmlHandler::NodeHandler * Fb2ReadHandler::RootHandler::NewTag(const QString &name, const QXmlAttributes &attributes)
 {
     switch (toKeyword(name)) {
         case Body   : return new BodyHandler(m_writer, name, attributes, "div", name);
@@ -190,7 +154,7 @@ Fb2ReadHandler::HeadHandler::HeadHandler(Fb2ReadWriter &writer, const QString &n
     if (hide) m_writer.writeAttribute("style", "display:none");
 }
 
-Fb2ReadHandler::BaseHandler * Fb2ReadHandler::HeadHandler::NewTag(const QString &name, const QXmlAttributes &attributes)
+Fb2XmlHandler::NodeHandler * Fb2ReadHandler::HeadHandler::NewTag(const QString &name, const QXmlAttributes &attributes)
 {
     Q_UNUSED(attributes);
     return new HeadHandler(m_writer, name);
@@ -225,7 +189,7 @@ Fb2ReadHandler::DescrHandler::DescrHandler(Fb2ReadWriter &writer, const QString
     m_writer.writeAttribute("id", m_writer.newId());
 }
 
-Fb2ReadHandler::BaseHandler * Fb2ReadHandler::DescrHandler::NewTag(const QString &name, const QXmlAttributes &attributes)
+Fb2XmlHandler::NodeHandler * Fb2ReadHandler::DescrHandler::NewTag(const QString &name, const QXmlAttributes &attributes)
 {
     Q_UNUSED(attributes);
     switch (toKeyword(name)) {
@@ -250,7 +214,7 @@ Fb2ReadHandler::TitleHandler::TitleHandler(Fb2ReadWriter &writer, const QString
     m_writer.writeAttribute("id", m_writer.newId());
 }
 
-Fb2ReadHandler::BaseHandler * Fb2ReadHandler::TitleHandler::NewTag(const QString &name, const QXmlAttributes &attributes)
+Fb2XmlHandler::NodeHandler * Fb2ReadHandler::TitleHandler::NewTag(const QString &name, const QXmlAttributes &attributes)
 {
     if (name == "annotation") return new BodyHandler(m_writer, name, attributes, "div", name);
     return new HeadHandler(m_writer, name, true);
@@ -324,7 +288,7 @@ void Fb2ReadHandler::BodyHandler::Init(const QXmlAttributes &attributes)
     }
 }
 
-Fb2ReadHandler::BaseHandler * Fb2ReadHandler::BodyHandler::NewTag(const QString &name, const QXmlAttributes &attributes)
+Fb2XmlHandler::NodeHandler * Fb2ReadHandler::BodyHandler::NewTag(const QString &name, const QXmlAttributes &attributes)
 {
     QString tag, style;
     switch (toKeyword(name)) {
@@ -414,69 +378,13 @@ void Fb2ReadHandler::BinaryHandler::EndTag(const QString &name)
 //---------------------------------------------------------------------------
 
 Fb2ReadHandler::Fb2ReadHandler(Fb2ReadThread &thread)
-    : QXmlDefaultHandler()
+    : Fb2XmlHandler()
     , m_writer(thread)
-    , m_handler(NULL)
 {
     m_writer.setAutoFormatting(true);
 }
 
-Fb2ReadHandler::~Fb2ReadHandler()
-{
-    if (m_handler) delete m_handler;
-}
-
-bool Fb2ReadHandler::startElement(const QString & namespaceURI, const QString & localName, const QString &qName, const QXmlAttributes &attributes)
-{
-    Q_UNUSED(namespaceURI);
-    Q_UNUSED(localName);
-
-    const QString name = qName.toLower();
-    if (m_handler) return m_handler->doStart(name, attributes);
-
-    qCritical() << name;
-
-    if (name == "fictionbook") {
-        m_handler = new RootHandler(m_writer, name);
-        return true;
-    } else {
-        m_error = QObject::tr("The file is not an FB2 file.");
-        return false;
-    }
-}
-
-static bool isWhiteSpace(const QString &str)
-{
-    return str.simplified().isEmpty();
-}
-
-bool Fb2ReadHandler::characters(const QString &str)
-{
-    QString s = str.simplified();
-    if (s.isEmpty()) return true;
-    if (isWhiteSpace(str.left(1))) s.prepend(" ");
-    if (isWhiteSpace(str.right(1))) s.append(" ");
-    return m_handler && m_handler->doText(s);
-}
-
-bool Fb2ReadHandler::endElement(const QString & namespaceURI, const QString & localName, const QString &qName)
-{
-    Q_UNUSED(namespaceURI);
-    Q_UNUSED(localName);
-    bool found = false;
-    return m_handler && m_handler->doEnd(qName.toLower(), found);
-}
-
-bool Fb2ReadHandler::fatalError(const QXmlParseException &exception)
-{
-    qCritical() << QObject::tr("Parse error at line %1, column %2: %3")
-       .arg(exception.lineNumber())
-       .arg(exception.columnNumber())
-       .arg(exception.message());
-    return false;
-}
-
-QString Fb2ReadHandler::errorString() const
+Fb2XmlHandler::NodeHandler * Fb2ReadHandler::CreateRoot(const QString &name)
 {
-    return m_error;
+    return new RootHandler(m_writer, name);
 }

+ 11 - 33
source/fb2read.h

@@ -53,42 +53,19 @@ private:
     int m_id;
 };
 
-class Fb2ReadHandler : public QXmlDefaultHandler
+class Fb2ReadHandler : public Fb2XmlHandler
 {
 public:
     explicit Fb2ReadHandler(Fb2ReadThread &thread);
-    virtual ~Fb2ReadHandler();
-    bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &attributes);
-    bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName);
-    bool characters(const QString &str);
-    bool fatalError(const QXmlParseException &exception);
-    QString errorString() const;
 
 private:
-    class BaseHandler
+    class BaseHandler : public NodeHandler
     {
     public:
         explicit BaseHandler(Fb2ReadWriter &writer, const QString &name)
-            : m_writer(writer), m_name(name), m_handler(0), m_closed(false) {}
-        virtual ~BaseHandler();
-        bool doStart(const QString &name, const QXmlAttributes &attributes);
-        bool doText(const QString &text);
-        bool doEnd(const QString &name, bool & found);
-    protected:
-        virtual BaseHandler * NewTag(const QString &name, const QXmlAttributes &attributes)
-            { Q_UNUSED(name); Q_UNUSED(attributes); return NULL; }
-        virtual void TxtTag(const QString &text)
-            { Q_UNUSED(text); }
-        virtual void EndTag(const QString &name)
-            { Q_UNUSED(name); }
-        const QString & Name() const
-            { return m_name; }
+            : NodeHandler(name), m_writer(writer) {}
     protected:
         Fb2ReadWriter &m_writer;
-    private:
-        const QString m_name;
-        BaseHandler * m_handler;
-        bool m_closed;
     };
 
     class RootHandler : public BaseHandler
@@ -102,7 +79,7 @@ private:
     public:
         explicit RootHandler(Fb2ReadWriter &writer, const QString &name);
     protected:
-        virtual BaseHandler * NewTag(const QString & name, const QXmlAttributes &attributes);
+        virtual NodeHandler * NewTag(const QString & name, const QXmlAttributes &attributes);
         virtual void EndTag(const QString &name);
     };
 
@@ -111,7 +88,7 @@ private:
     public:
         explicit HeadHandler(Fb2ReadWriter &writer, const QString &name, bool hide = false);
     protected:
-        virtual BaseHandler * NewTag(const QString &name, const QXmlAttributes &attributes);
+        virtual NodeHandler * NewTag(const QString &name, const QXmlAttributes &attributes);
         virtual void TxtTag(const QString &text);
         virtual void EndTag(const QString &name);
     };
@@ -127,7 +104,7 @@ private:
     public:
         explicit DescrHandler(Fb2ReadWriter &writer, const QString &name);
     protected:
-        virtual BaseHandler * NewTag(const QString &name, const QXmlAttributes &attributes);
+        virtual NodeHandler * NewTag(const QString &name, const QXmlAttributes &attributes);
     };
 
     class TitleHandler : public HeadHandler
@@ -135,7 +112,7 @@ private:
     public:
         explicit TitleHandler(Fb2ReadWriter &writer, const QString &name);
     protected:
-        virtual BaseHandler * NewTag(const QString &name, const QXmlAttributes &attributes);
+        virtual NodeHandler * NewTag(const QString &name, const QXmlAttributes &attributes);
     };
 
     class BodyHandler : public BaseHandler
@@ -158,7 +135,7 @@ private:
         explicit BodyHandler(Fb2ReadWriter &writer, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style = QString());
         explicit BodyHandler(BodyHandler *parent, const QString &name, const QXmlAttributes &attributes, const QString &tag, const QString &style = QString());
     protected:
-        virtual BaseHandler * NewTag(const QString &name, const QXmlAttributes &attributes);
+        virtual NodeHandler * NewTag(const QString &name, const QXmlAttributes &attributes);
         virtual void TxtTag(const QString &text);
         virtual void EndTag(const QString &name);
     protected:
@@ -194,10 +171,11 @@ private:
         QString m_text;
     };
 
+protected:
+    virtual NodeHandler * CreateRoot(const QString &name);
+
 private:
     Fb2ReadWriter m_writer;
-    RootHandler * m_handler;
-    QString m_error;
 };
 
 #endif // FB2READ_H

+ 98 - 0
source/fb2xml.cpp

@@ -0,0 +1,98 @@
+#include "fb2xml.h"
+#include <QtDebug>
+
+//---------------------------------------------------------------------------
+//  Fb2XmlHandler::NodeHandler
+//---------------------------------------------------------------------------
+
+bool Fb2XmlHandler::NodeHandler::doStart(const QString &name, const QXmlAttributes &attributes)
+{
+    if (m_handler) return m_handler->doStart(name, attributes);
+    m_handler = NewTag(name, attributes); if (m_handler) return true;
+//    qCritical() << QObject::tr("Unknown XML child tag: <%1> <%2>").arg(m_name).arg(name);
+    m_handler = new NodeHandler(name);
+    return true;
+}
+
+bool Fb2XmlHandler::NodeHandler::doText(const QString &text)
+{
+    if (m_handler) m_handler->doText(text); else TxtTag(text);
+    return true;
+}
+
+bool Fb2XmlHandler::NodeHandler::doEnd(const QString &name, bool & exists)
+{
+    if (m_handler) {
+        bool found = exists || name == m_name;
+        m_handler->doEnd(name, found);
+        if (m_handler->m_closed) { delete m_handler; m_handler = NULL; }
+        if (found) { exists = true; return true; }
+    }
+    bool found = name == m_name;
+    if (!found) qCritical() << QObject::tr("Conglict XML tags: <%1>  </%2>").arg(m_name).arg(name);
+    m_closed = found || exists;
+    if (m_closed) EndTag(m_name);
+    exists = found;
+    return true;
+}
+
+//---------------------------------------------------------------------------
+//  Fb2XmlHandler
+//---------------------------------------------------------------------------
+
+Fb2XmlHandler::Fb2XmlHandler()
+    : QXmlDefaultHandler()
+    , m_handler(0)
+{
+}
+
+Fb2XmlHandler::~Fb2XmlHandler()
+{
+    if (m_handler) delete m_handler;
+}
+
+bool Fb2XmlHandler::startElement(const QString & namespaceURI, const QString & localName, const QString &qName, const QXmlAttributes &attributes)
+{
+    Q_UNUSED(namespaceURI);
+    Q_UNUSED(localName);
+    const QString name = qName.toLower();
+    if (m_handler) return m_handler->doStart(name, attributes);
+    return m_handler = CreateRoot(name);
+}
+
+static bool isWhiteSpace(const QString &str)
+{
+    return str.simplified().isEmpty();
+}
+
+bool Fb2XmlHandler::characters(const QString &str)
+{
+    QString s = str.simplified();
+    if (s.isEmpty()) return true;
+    if (isWhiteSpace(str.left(1))) s.prepend(" ");
+    if (isWhiteSpace(str.right(1))) s.append(" ");
+    return m_handler && m_handler->doText(s);
+}
+
+bool Fb2XmlHandler::endElement(const QString & namespaceURI, const QString & localName, const QString &qName)
+{
+    Q_UNUSED(namespaceURI);
+    Q_UNUSED(localName);
+    bool found = false;
+    return m_handler && m_handler->doEnd(qName.toLower(), found);
+}
+
+bool Fb2XmlHandler::fatalError(const QXmlParseException &exception)
+{
+    qCritical() << QObject::tr("Parse error at line %1, column %2: %3")
+       .arg(exception.lineNumber())
+       .arg(exception.columnNumber())
+       .arg(exception.message());
+    return false;
+}
+
+QString Fb2XmlHandler::errorString() const
+{
+    return m_error;
+}
+

+ 46 - 0
source/fb2xml.h

@@ -2,6 +2,7 @@
 #define FB2XML_H
 
 #include <QHash>
+#include <QXmlDefaultHandler>
 
 #define FB2_BEGIN_KEYLIST private: enum Keyword {
 
@@ -22,4 +23,49 @@ x::KeywordHash::KeywordHash() {
 
 #define FB2_KEY(key,str) insert(str,key);
 
+class Fb2XmlHandler : public QXmlDefaultHandler
+{
+public:
+    explicit Fb2XmlHandler();
+    virtual ~Fb2XmlHandler();
+    bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &attributes);
+    bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName);
+    bool characters(const QString &str);
+    bool fatalError(const QXmlParseException &exception);
+    QString errorString() const;
+
+protected:
+    class NodeHandler
+    {
+    public:
+        explicit NodeHandler(const QString &name)
+            : m_name(name), m_handler(0), m_closed(false) {}
+        virtual ~NodeHandler()
+            { if (m_handler) delete m_handler; }
+        bool doStart(const QString &name, const QXmlAttributes &attributes);
+        bool doText(const QString &text);
+        bool doEnd(const QString &name, bool & found);
+    protected:
+        virtual NodeHandler * NewTag(const QString &name, const QXmlAttributes &attributes)
+            { Q_UNUSED(name); Q_UNUSED(attributes); return NULL; }
+        virtual void TxtTag(const QString &text)
+            { Q_UNUSED(text); }
+        virtual void EndTag(const QString &name)
+            { Q_UNUSED(name); }
+        const QString & Name() const
+            { return m_name; }
+    private:
+        const QString m_name;
+        NodeHandler * m_handler;
+        bool m_closed;
+    };
+
+protected:
+    virtual NodeHandler * CreateRoot(const QString &name) = 0;
+
+private:
+    NodeHandler * m_handler;
+    QString m_error;
+};
+
 #endif // FB2XML_H