trying to use QXmlParser and friends
-
Hi all -
I'm trying to use the Qt facility for processing an XML file. I've read the docs on the various classes for this, and I've gotten this far:
QXmlSimpleReader reader; QXmlDefaultHandler handler; QString filename("./testfile.xml"); QFile file(filename); QXmlInputSource *source; rc = file.open(QFile::ReadOnly); source = new QXmlInputSource(&file); source->fetchData(); reader.setContentHandler(&handler); reader.setErrorHandler(&handler); reader.parse(source);
This runs without error, but I'm not sure what it accomplishes. The docs suggest that the default handler "provides sensible default behavior" but also it says that, for example, the startEntity method does nothing (which I suppose is somewhat sensible).
So, do I have to subclass the default handler or not?
Thanks...
-
Hi
I have not tried with QXmlInputSource and friends.
i used this tut to try parse something.https://www.walletfox.com/course/qxmlstreamreaderexample.php
Found it good to explain how it works as.
Do note that this uses a sax interface where its parsed on the fly.
There is also
https://doc.qt.io/qt-5/qdomdocument.htmlwhere it read to a tree in memory.
This is much easier to update than the SAX way but SAX way can parse a GIGA file
where qdomdocument runs out of memory. -
This runs without error, but I'm not sure what it accomplishes.
It parses the XML file i.e. walks through the entire structure splitting it to the little bits and pieces and reports them as callbacks to the handler. The default handler handles those pieces by doing nothing with them.
So, do I have to subclass the default handler or not?
Yes, specifically implement those virtual functions that handle the data you're interested in. For example if you're interested in an attribute of a particular node you could implement startElement() and look for the name you want.
Alternatively you could subclass the base classes for given handler types, like
QXmlErrorHandler
orQXmlLexicalHandler
, but those are pure virtual bases, meaning you would have to implement everything in them by yourself and chances are you're not interested in most of it. It's easier to subclassQXmlDefaultHandler
which provides empty implementations for everything. -
@Chris-Kawa OK, progress is being made. I've sub-classed the default handler, and the startElement() and endElement() methods. In my other XML parser (expat) there was also a routine handleData() which was used to get the content between the start and end tags. I don't see an equivalent to that in QXmlDefaultHandler; how do I retrieve that data?
Thanks...
-
how do I retrieve that data?
-
@Chris-Kawa oh my goodness, that is a thing of beauty.
Thanks to all who helped.
EDIT: actually, I do have a follow-on question: this will allow me to build my map of tags and content. I need to export that map when I'm done. I'm thinking of making the map a member variable, and adding a method that returns it. Is there a better way to do this?
-
I'm thinking of making the map a member variable, and adding a method that returns it. Is there a better way to do this?
So an XMLTagMapMakerHandler? Sounds good to me.
-
Well, I shouldn't have declared victory so quickly. When I migrated my test code into my app, I got this error:
C:\wifibutton\utility\xmlparser.h:16: error: 'XmlHandler' does not name a type; did you mean 'XmlParser'? XmlHandler m_handler; ^~~~~~~~~~ XmlParser
Here are some snippets:
class XmlHandler : public QXmlDefaultHandler { private: MsgHash m_hash; public: XmlHandler(); ... }
#include "xmlhandler.h" class XmlParser { QXmlSimpleReader m_reader; XmlHandler m_handler; ... }
Is there something special I need to know about sub-classing QXmlDefaultHandler, or am I just brain-fading here?
Thanks...
-
Yes, I did.
Here's the complete code from the headers:
xmlhandler.h
#ifndef XMLHANDLER_H #define XMLHANDLER_H #include <QXmlDefaultHandler> #include "message.h" using namespace std; class XmlHandler : public QXmlDefaultHandler { private: MsgHash m_hash; bool m_tagStarted = false; QString m_tag; QString m_data; QXmlInputSource *m_source; public: XmlHandler(); ~XmlHandler(); bool startElement(const QString &uri, const QString &local, const QString &name, const QXmlAttributes &atts) override; bool endElement(const QString &uri, const QString &local, const QString &name) override; bool characters(const QString &ch) override; void getHash(MsgHash &msgHash) {msgHash = m_hash;} }; #endif // XMLHANDLER_H
xmlparser.h:
#ifndef XMLPARSER_H #define XMLPARSER_H #include <stdint.h> #include <QXmlDefaultHandler> #include <QXmlSimpleReader> #include "constants.h" #include "message.h" #include "xmlhandler.h" class XmlParser { QXmlSimpleReader m_reader; XmlHandler m_handler; public: XmlParser(); ~XmlParser(); int process(string xml, MsgHash &msgHash); }; #endif // XMLPARSER_H
-
Hi
It looks ok.
Could you try add some dummy class to the xmlhandler.hclass Test {
};and see if it can see that symbol ?
just to test it dont see the include and not something with class XmlHandler
-
Super :)
Well it's my number one suspect when it says "don't know symbol"
and you check you have the header included and all seem fine.