fb2xml2.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. #include "fb2xml2.h"
  2. #ifdef FB2_USE_LIBXML2
  3. #include <cstring>
  4. #include <libxml/tree.h>
  5. #include <libxml/parser.h>
  6. #include <libxml/HTMLparser.h>
  7. #include <libxml/xmlreader.h>
  8. #include <QtDebug>
  9. namespace XML2 {
  10. //---------------------------------------------------------------------------
  11. // XML2::XmlReader
  12. //---------------------------------------------------------------------------
  13. class XmlReaderLocator : public QXmlLocator {
  14. public:
  15. XmlReaderLocator(XmlReader* r) : reader(r) {}
  16. virtual int columnNumber(void) const;
  17. virtual int lineNumber(void) const;
  18. private:
  19. XmlReader* reader;
  20. };
  21. class XmlReaderPrivate {
  22. public:
  23. ~XmlReaderPrivate(void) {}
  24. private:
  25. XmlReaderPrivate(XmlReader* reader);
  26. static void onError(void *arg, const char *msg, xmlParserSeverities severity, xmlTextReaderLocatorPtr locator);
  27. static int onRead(void * context, char * buffer, int len);
  28. static QString C2S(const xmlChar* text, int size = -1);
  29. bool parse(const QXmlInputSource *input);
  30. bool parse(QIODevice *input);
  31. void process(xmlTextReaderPtr reader);
  32. QScopedPointer<XmlReaderLocator> locator;
  33. Q_DECLARE_PUBLIC(XmlReader)
  34. XmlReader* q_ptr;
  35. QXmlEntityResolver* entityresolver;
  36. QXmlDTDHandler* dtdhandler;
  37. QXmlContentHandler* contenthandler;
  38. QXmlErrorHandler* errorhandler;
  39. QXmlLexicalHandler* lexicalhandler;
  40. QXmlDeclHandler* declhandler;
  41. xmlTextReaderPtr m_reader;
  42. friend class XmlReaderLocator;
  43. };
  44. XmlReaderPrivate::XmlReaderPrivate(XmlReader* reader)
  45. : q_ptr(reader), entityresolver(0), dtdhandler(0), contenthandler(0), errorhandler(0), lexicalhandler(0), declhandler(0), m_reader(0)
  46. {
  47. this->locator.reset(new XmlReaderLocator(reader));
  48. }
  49. QString XmlReaderPrivate::C2S(const xmlChar* text, int size)
  50. {
  51. return QString::fromLocal8Bit(reinterpret_cast<const char*>(text), size);
  52. }
  53. void XmlReaderPrivate::onError(void * arg, const char * msg, xmlParserSeverities severity, xmlTextReaderLocatorPtr locator)
  54. {
  55. XmlReaderPrivate* r = reinterpret_cast<XmlReaderPrivate*>(arg);
  56. if (r->errorhandler) {
  57. QXmlParseException e(QString::fromLocal8Bit(msg), xmlTextReaderGetParserColumnNumber(r->m_reader), xmlTextReaderGetParserLineNumber(r->m_reader));
  58. switch (severity) {
  59. case XML_PARSER_SEVERITY_VALIDITY_WARNING: r->errorhandler->warning(e); break;
  60. case XML_PARSER_SEVERITY_VALIDITY_ERROR: r->errorhandler->error(e); break;
  61. case XML_PARSER_SEVERITY_WARNING: r->errorhandler->warning(e); break;
  62. case XML_PARSER_SEVERITY_ERROR: r->errorhandler->error(e); break;
  63. }
  64. }
  65. }
  66. void XmlReaderPrivate::process(xmlTextReaderPtr reader)
  67. {
  68. if (!contenthandler) return;
  69. switch (xmlTextReaderNodeType(reader)) {
  70. case XML_READER_TYPE_ELEMENT: {
  71. QString localName = C2S(xmlTextReaderConstLocalName(reader));
  72. QString qName = C2S(xmlTextReaderConstName(reader));
  73. bool empty = xmlTextReaderIsEmptyElement(reader);
  74. QXmlAttributes atts;
  75. while (xmlTextReaderMoveToNextAttribute(reader)) {
  76. QString localName = C2S(xmlTextReaderConstLocalName(reader));
  77. QString qName = C2S(xmlTextReaderConstName(reader));
  78. QString value = C2S(xmlTextReaderConstValue(reader));
  79. atts.append(qName, "", localName, value);
  80. }
  81. contenthandler->startElement("", localName, qName, atts);
  82. if (empty) contenthandler->endElement("", localName, qName);
  83. } break;
  84. case XML_READER_TYPE_TEXT: {
  85. QString value = C2S(xmlTextReaderConstValue(reader));
  86. contenthandler->characters(value);
  87. } break;
  88. case XML_READER_TYPE_END_ELEMENT: {
  89. QString localName = C2S(xmlTextReaderConstLocalName(reader));
  90. QString qName = C2S(xmlTextReaderConstName(reader));
  91. contenthandler->endElement("", localName, qName);
  92. } break;
  93. case XML_READER_TYPE_COMMENT: {
  94. if (lexicalhandler) {
  95. QString value = C2S(xmlTextReaderConstValue(reader));
  96. lexicalhandler->comment(value);
  97. }
  98. } break;
  99. }
  100. }
  101. int XmlReaderPrivate::onRead(void * context, char * buffer, int len)
  102. {
  103. QIODevice *device = reinterpret_cast<QIODevice*>(context);
  104. return device->read(buffer, len);
  105. }
  106. bool XmlReaderPrivate::parse(const QXmlInputSource *input)
  107. {
  108. QByteArray arr = input->data().toUtf8();
  109. int options = XML_PARSE_RECOVER | XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NONET;
  110. m_reader = xmlReaderForMemory(arr.constData(), arr.size(), NULL, NULL, options);
  111. if (!m_reader) return false;
  112. xmlTextReaderSetErrorHandler(m_reader, &XmlReaderPrivate::onError, this);
  113. while (xmlTextReaderRead(m_reader) == 1) process(m_reader);
  114. xmlFreeTextReader(m_reader);
  115. return true;
  116. }
  117. bool XmlReaderPrivate::parse(QIODevice *input)
  118. {
  119. int options = XML_PARSE_RECOVER | XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NONET;
  120. m_reader = xmlReaderForIO(&XmlReaderPrivate::onRead, NULL, input, NULL, NULL, options);
  121. if (!m_reader) return false;
  122. xmlTextReaderSetErrorHandler(m_reader, &XmlReaderPrivate::onError, this);
  123. while (xmlTextReaderRead(m_reader) == 1) process(m_reader);
  124. xmlFreeTextReader(m_reader);
  125. return true;
  126. }
  127. XmlReader::XmlReader(void)
  128. : d_ptr(new XmlReaderPrivate(this))
  129. {
  130. }
  131. XmlReader::~XmlReader(void)
  132. {
  133. }
  134. bool XmlReader::feature(const QString&, bool* ok) const
  135. {
  136. if (ok) *ok = false;
  137. return false;
  138. }
  139. void XmlReader::setFeature(const QString&, bool)
  140. {
  141. }
  142. bool XmlReader::hasFeature(const QString&) const
  143. {
  144. return false;
  145. }
  146. void* XmlReader::property(const QString&, bool* ok) const
  147. {
  148. if (ok) *ok = false;
  149. return 0;
  150. }
  151. void XmlReader::setProperty(const QString&, void*)
  152. {
  153. }
  154. bool XmlReader::hasProperty(const QString&) const
  155. {
  156. return false;
  157. }
  158. void XmlReader::setEntityResolver(QXmlEntityResolver* handler)
  159. {
  160. Q_D(XmlReader);
  161. d->entityresolver = handler;
  162. }
  163. QXmlEntityResolver* XmlReader::entityResolver(void) const
  164. {
  165. const XmlReaderPrivate* d = this->d_func();
  166. return d->entityresolver;
  167. }
  168. void XmlReader::setDTDHandler(QXmlDTDHandler* handler)
  169. {
  170. Q_D(XmlReader);
  171. d->dtdhandler = handler;
  172. }
  173. QXmlDTDHandler* XmlReader::DTDHandler(void) const
  174. {
  175. const XmlReaderPrivate* d = this->d_func();
  176. return d->dtdhandler;
  177. }
  178. void XmlReader::setContentHandler(QXmlContentHandler* handler)
  179. {
  180. Q_D(XmlReader);
  181. d->contenthandler = handler;
  182. }
  183. QXmlContentHandler* XmlReader::contentHandler(void) const
  184. {
  185. const XmlReaderPrivate* d = this->d_func();
  186. return d->contenthandler;
  187. }
  188. void XmlReader::setErrorHandler(QXmlErrorHandler* handler)
  189. {
  190. Q_D(XmlReader);
  191. d->errorhandler = handler;
  192. }
  193. QXmlErrorHandler* XmlReader::errorHandler(void) const
  194. {
  195. const XmlReaderPrivate* d = this->d_func();
  196. return d->errorhandler;
  197. }
  198. void XmlReader::setLexicalHandler(QXmlLexicalHandler* handler)
  199. {
  200. Q_D(XmlReader);
  201. d->lexicalhandler = handler;
  202. }
  203. QXmlLexicalHandler* XmlReader::lexicalHandler(void) const
  204. {
  205. const XmlReaderPrivate* d = this->d_func();
  206. return d->lexicalhandler;
  207. }
  208. void XmlReader::setDeclHandler(QXmlDeclHandler* handler)
  209. {
  210. Q_D(XmlReader);
  211. d->declhandler = handler;
  212. }
  213. QXmlDeclHandler* XmlReader::declHandler(void) const
  214. {
  215. const XmlReaderPrivate* d = this->d_func();
  216. return d->declhandler;
  217. }
  218. bool XmlReader::parse(const QXmlInputSource& input)
  219. {
  220. return this->parse(&input);
  221. }
  222. bool XmlReader::parse(const QXmlInputSource* input)
  223. {
  224. Q_D(XmlReader);
  225. if (d->contenthandler) {
  226. d->contenthandler->setDocumentLocator(d->locator.data());
  227. }
  228. d->parse(input);
  229. return true;
  230. }
  231. bool XmlReader::parse(QIODevice *input)
  232. {
  233. Q_D(XmlReader);
  234. if (d->contenthandler) {
  235. d->contenthandler->setDocumentLocator(d->locator.data());
  236. }
  237. d->parse(input);
  238. return true;
  239. }
  240. int XmlReaderLocator::columnNumber(void) const
  241. {
  242. return xmlTextReaderGetParserColumnNumber(this->reader->d_func()->m_reader);
  243. }
  244. int XmlReaderLocator::lineNumber(void) const
  245. {
  246. return xmlTextReaderGetParserLineNumber(this->reader->d_func()->m_reader);
  247. }
  248. } // namespace XML2
  249. #endif // FB2_USE_LIBXML2