main.cpp
1 #include <QtGui> 2 #include <iostream> 3 4 #include "saxhandler.h" 5 6 int main(int argc, char *argv[]) 7 { 8 QApplication app(argc, argv); 9 QDir::setCurrent(app.applicationDirPath());//设置路径为当前目录 10 11 12 QStringList labels; 13 labels << QObject::tr("Terms") << QObject::tr("Pages"); 14 15 QTreeWidget treeWidget; 16 treeWidget.setHeaderLabels(labels); 17 treeWidget.header()->setResizeMode(QHeaderView::Stretch); 18 treeWidget.setWindowTitle(QObject::tr("SAX Handler")); 19 treeWidget.show(); 20 21 SaxHandler handler(&treeWidget); 22 handler.readFile("in1.xml"); 23 24 return app.exec(); 25 }
saxhandler.h
#ifndef SAXHANDLER_H #define SAXHANDLER_H #include <QXmlDefaultHandler> class QTreeWidget; class QTreeWidgetItem; class SaxHandler : public QXmlDefaultHandler { public: SaxHandler(QTreeWidget *tree); bool readFile(const QString &fileName); protected: 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); private: //树控件窗口 QTreeWidget *treeWidget; //树控件项 QTreeWidgetItem *currentItem; QString currentText; }; #endif
saxhandler.cpp
1 #include <QtGui> 2 #include <iostream> 3 4 #include "saxhandler.h" 5 6 SaxHandler::SaxHandler(QTreeWidget *tree) 7 { 8 treeWidget = tree; 9 } 10 11 //接受用存储在XML文件中的信息进行组装的QTreeWidget 12 //要获得要解析文件的文件名时,会调用这个函数. 13 bool SaxHandler::readFile(const QString &fileName) 14 { 15 currentItem = 0; 16 17 QFile file(fileName); 18 //用来读取文件 19 QXmlInputSource inputSource(&file); 20 //用来解析这个文件 21 QXmlSimpleReader reader; 22 reader.setContentHandler(this); 23 reader.setErrorHandler(this); 24 //调用pause来进行解析 25 return reader.parse(inputSource); 26 } 27 28 //当阅读器遇到一个新的打开标签时,就会调用startElement()函数. 29 //第三个参数是标签的名称,第四个参数是属性列表. 30 bool SaxHandler::startElement(const QString & /* namespaceURI */, 31 const QString & /* localName */, 32 const QString &qName, 33 const QXmlAttributes &attributes) 34 { 35 //如果是<entry> 36 if (qName == "entry") { 37 //创建一个新的QTreeWidgetItem项,如果currentItem存在则以此为 38 //父对象,如果不存在则以treeWidget根为父对象 39 currentItem = new QTreeWidgetItem(currentItem ? 40 currentItem : treeWidget->invisibleRootItem()); 41 //设置文本 42 currentItem->setText(0, attributes.value("term")); 43 } 44 else if (qName == "page") 45 { 46 //currentText是一个累加器,用于处理<page>之间的文本 47 currentText.clear(); 48 } 49 return true; 50 } 51 52 //可以把字符数据添加到currentText变量中,当遇到字符数据时进行操作 53 bool SaxHandler::characters(const QString &str) 54 { 55 currentText += str; 56 return true; 57 } 58 59 //当遇到一个关闭标签会调用endElement.第三个参数是标签的名称. 60 bool SaxHandler::endElement(const QString & /* namespaceURI */, 61 const QString & /* localName */, 62 const QString &qName) 63 { 64 //如果是</entry>则更新currentItem私有变量 65 //使它指向当前QTreeWidgetItem的父对象 66 if (qName == "entry") { 67 currentItem = currentItem->parent(); 68 } 69 //如果为</page>,则把指定的页码或者范围添加到这一列当前项的文本 70 else if (qName == "page") 71 { 72 if (currentItem) 73 { 74 QString allPages = currentItem->text(1); 75 if (!allPages.isEmpty()) 76 allPages += ", "; 77 allPages += currentText; 78 currentItem->setText(1, allPages); 79 } 80 } 81 return true; 82 } 83 84 //解析失败会调用fatalError函数,给出行号,列号,以及这个解析器的错误文本 85 bool SaxHandler::fatalError(const QXmlParseException &exception) 86 { 87 std::cerr << "Parse error at line " << exception.lineNumber() 88 << ", " << "column " << exception.columnNumber() << ": " 89 << qPrintable(exception.message()) << std::endl; 90 return false; 91 }