Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1655851
  • 博文数量: 1493
  • 博客积分: 38
  • 博客等级: 民兵
  • 技术积分: 5834
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-19 17:28
文章分类

全部博文(1493)

文章存档

2016年(11)

2015年(38)

2014年(137)

2013年(253)

2012年(1054)

2011年(1)

分类: 嵌入式

2013-12-26 14:49:08

原文地址:Qt使用 DOM 处理 XML 作者:luozhiyong131

DOM 是由 W3C 提出的一种处理 XML 文档的标准接口.DOM 一次性读入整个 XML 文档,在内存中构造为一棵树(被称为 DOM 树)。我们能够在这棵树上进行导航,比如移动到下一节点或者返回上一节点,也可以对这棵树进行修改,或者是直接将这颗树保存为硬盘上的一个 XML 文件。

下面一个 XML 片段:

点击(此处)折叠或打开

  1. <doc>
  2.     <quote>Scio me nihil scire</quote>
  3.     <translation>I know that I know nothing</translation>
  4. </doc>
我们可以认为是如下一棵 DOM 树:

点击(此处)折叠或打开

  1. Document
  2.   |--Element(doc)
  3.        |--Element(quote)
  4.        | |--Text("Scio me nihil scire")
  5.        |--Element(translation)
  6.             |--Text("I know that I know nothing")

在 Qt 中,所有 DOM 节点的类型名字都以 QDom 开头,因此,QDomElement就是 Element 节点,QDomText就是 Text 节点。不同类型的节点则有不同类型的子节点。例如,Element 节点允许包含其它 Element 节点,也可以是其它类型,

books.xml 这个文件来作示例:

点击(此处)折叠或打开

  1. <bookindex>
  2.     <entry term="sidebearings">
  3.         <page>10</page>
  4.         <page>34-35</page>
  5.         <page>307-308</page>
  6.     </entry>
  7.     <entry term="subtraction">
  8.         <entry term="of pictures">
  9.             <page>115</page>
  10.             <page>244</page>
  11.         </entry>
  12.         <entry term="of vectors">
  13.             <page>9</page>
  14.         </entry>
  15.     </entry>
  16. </bookindex>
需要在 .pro 文件中添加这么一句:
QT+=xml

头文件也是类似的:

点击(此处)折叠或打开

  1. class MainWindow : public QMainWindow
  2. {
  3.     Q_OBJECT
  4. public:
  5.     MainWindow(QWidget *parent = 0);
  6.     ~MainWindow();

  7.     bool readFile(const QString &fileName);
  8. private:
  9.     void parseBookindexElement(const QDomElement &element);
  10.     void parseEntryElement(const QDomElement &element, QTreeWidgetItem *parent);
  11.     void parsePageElement(const QDomElement &element, QTreeWidgetItem *parent);
  12.     QTreeWidget *treeWidget;
  13. };
MainWindow的构造函数和析构函数

点击(此处)折叠或打开

  1. MainWindow::MainWindow(QWidget *parent)
  2.     : QMainWindow(parent)
  3. {
  4.     setWindowTitle(tr("XML DOM Reader"));

  5.     treeWidget = new QTreeWidget(this);
  6.     QStringList headers;
  7.     headers << "Items" << "Pages"; treeWidget->setHeaderLabels(headers);
  8.     setCentralWidget(treeWidget);
  9. }

  10. MainWindow::~MainWindow()
  11. {
  12. }

点击(此处)折叠或打开

  1. bool MainWindow::readFile(const QString &fileName)
  2. {
  3.     QFile file(fileName);
  4.     if (!file.open(QFile::ReadOnly | QFile::Text)) {
  5.         QMessageBox::critical(this, tr("Error"),
  6.                               tr("Cannot read file %1").arg(fileName));
  7.         return false;
  8.     }

  9.     QString errorStr;
  10.     int errorLine;
  11.     int errorColumn;

  12.   QDomDocument doc;
  13.   /**
  14.    * 第二个参数确定是否处理命名空间,
  15.    * 如果设置为 true,处理器会自动设置标签的前缀之类,
  16.    * 因为我们的 XML 文档没有命名空间,所以直接设置为 false;
  17.    * 剩下的三个参数都是关于错误处理。后三个参数都是输出参数,
  18.    */
  19.     if (!doc.setContent(&file, false, &errorStr, &errorLine, &errorColumn)) { //填充 DOM 树
  20.         QMessageBox::critical(this, tr("Error"),
  21.                               tr("Parse error at line %1, column %2: %3")
  22.                                 .arg(errorLine).arg(errorColumn).arg(errorStr));
  23.         return false;
  24.     }

  25.     QDomElement root = doc.documentElement(); //获得一个 Document 元素
  26.     if (root.tagName() != "bookindex") {
  27.         QMessageBox::critical(this, tr("Error"),
  28.                               tr("Not a bookindex file"));
  29.         return false;
  30.     }

  31.     parseBookindexElement(root);
  32.     return true;
  33. }

  34. void MainWindow::parseBookindexElement(const QDomElement &element)
  35. {
  36.     QDomNode child = element.firstChild();
  37.     while (!child.isNull()) {
  38.         if (child.toElement().tagName() == "entry") {
  39.             parseEntryElement(child.toElement(),
  40.                               treeWidget->invisibleRootItem());
  41.         }
  42.         child = child.nextSibling(); //取下一个标签
  43.     }
  44. }

  45. void MainWindow::parseEntryElement(const QDomElement &element,
  46.                                    QTreeWidgetItem *parent)
  47. {
  48.     QTreeWidgetItem *item = new QTreeWidgetItem(parent);
  49.     item->setText(0, element.attribute("term"));

  50.     QDomNode child = element.firstChild();
  51.     while (!child.isNull()) {
  52.         if (child.toElement().tagName() == "entry") {
  53.             parseEntryElement(child.toElement(), item);
  54.         } else if (child.toElement().tagName() == "page") {
  55.             parsePageElement(child.toElement(), item);
  56.         }
  57.         child = child.nextSibling();
  58.     }
  59. }
  60. void MainWindow::parsePageElement(const QDomElement &element,
  61.                                   QTreeWidgetItem *parent)
  62. {
  63.     QString page = element.text();
  64.     QString allPages = parent->text(1);
  65.     if (!allPages.isEmpty()) {
  66.          allPages += ", ";
  67.     }
  68.     allPages += page;
  69.     parent->setText(1, allPages);
  70. }

阅读(872) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~