DOM 是由 W3C 提出的一种处理 XML 文档的标准接口.DOM 一次性读入整个 XML 文档,在内存中构造为一棵树(被称为 DOM 树)。我们能够在这棵树上进行导航,比如移动到下一节点或者返回上一节点,也可以对这棵树进行修改,或者是直接将这颗树保存为硬盘上的一个 XML 文件。
下面一个 XML 片段:
-
<doc>
-
<quote>Scio me nihil scire</quote>
-
<translation>I know that I know nothing</translation>
-
</doc>
我们可以认为是如下一棵 DOM 树:
-
Document
-
|--Element(doc)
-
|--Element(quote)
-
| |--Text("Scio me nihil scire")
-
|--Element(translation)
-
|--Text("I know that I know nothing")
在 Qt 中,所有 DOM 节点的类型名字都以 QDom 开头,因此,QDomElement就是 Element 节点,QDomText就是 Text 节点。不同类型的节点则有不同类型的子节点。例如,Element 节点允许包含其它 Element 节点,也可以是其它类型,
books.xml 这个文件来作示例:
-
<bookindex>
-
<entry term="sidebearings">
-
<page>10</page>
-
<page>34-35</page>
-
<page>307-308</page>
-
</entry>
-
<entry term="subtraction">
-
<entry term="of pictures">
-
<page>115</page>
-
<page>244</page>
-
</entry>
-
<entry term="of vectors">
-
<page>9</page>
-
</entry>
-
</entry>
-
</bookindex>
需要在 .pro 文件中添加这么一句:QT+=xml
头文件也是类似的:
-
class MainWindow : public QMainWindow
-
{
-
Q_OBJECT
-
public:
-
MainWindow(QWidget *parent = 0);
-
~MainWindow();
-
-
bool readFile(const QString &fileName);
-
private:
-
void parseBookindexElement(const QDomElement &element);
-
void parseEntryElement(const QDomElement &element, QTreeWidgetItem *parent);
-
void parsePageElement(const QDomElement &element, QTreeWidgetItem *parent);
-
QTreeWidget *treeWidget;
-
};
MainWindow的构造函数和析构函数
-
MainWindow::MainWindow(QWidget *parent)
-
: QMainWindow(parent)
-
{
-
setWindowTitle(tr("XML DOM Reader"));
-
-
treeWidget = new QTreeWidget(this);
-
QStringList headers;
-
headers << "Items" << "Pages"; treeWidget->setHeaderLabels(headers);
-
setCentralWidget(treeWidget);
-
}
-
-
MainWindow::~MainWindow()
-
{
-
}
-
bool MainWindow::readFile(const QString &fileName)
-
{
-
QFile file(fileName);
-
if (!file.open(QFile::ReadOnly | QFile::Text)) {
-
QMessageBox::critical(this, tr("Error"),
-
tr("Cannot read file %1").arg(fileName));
-
return false;
-
}
-
-
QString errorStr;
-
int errorLine;
-
int errorColumn;
-
-
QDomDocument doc;
-
/**
-
* 第二个参数确定是否处理命名空间,
-
* 如果设置为 true,处理器会自动设置标签的前缀之类,
-
* 因为我们的 XML 文档没有命名空间,所以直接设置为 false;
-
* 剩下的三个参数都是关于错误处理。后三个参数都是输出参数,
-
*/
-
if (!doc.setContent(&file, false, &errorStr, &errorLine, &errorColumn)) { //填充 DOM 树
-
QMessageBox::critical(this, tr("Error"),
-
tr("Parse error at line %1, column %2: %3")
-
.arg(errorLine).arg(errorColumn).arg(errorStr));
-
return false;
-
}
-
-
QDomElement root = doc.documentElement(); //获得一个 Document 元素
-
if (root.tagName() != "bookindex") {
-
QMessageBox::critical(this, tr("Error"),
-
tr("Not a bookindex file"));
-
return false;
-
}
-
-
parseBookindexElement(root);
-
return true;
-
}
-
-
void MainWindow::parseBookindexElement(const QDomElement &element)
-
{
-
QDomNode child = element.firstChild();
-
while (!child.isNull()) {
-
if (child.toElement().tagName() == "entry") {
-
parseEntryElement(child.toElement(),
-
treeWidget->invisibleRootItem());
-
}
-
child = child.nextSibling(); //取下一个标签
-
}
-
}
-
-
void MainWindow::parseEntryElement(const QDomElement &element,
-
QTreeWidgetItem *parent)
-
{
-
QTreeWidgetItem *item = new QTreeWidgetItem(parent);
-
item->setText(0, element.attribute("term"));
-
-
QDomNode child = element.firstChild();
-
while (!child.isNull()) {
-
if (child.toElement().tagName() == "entry") {
-
parseEntryElement(child.toElement(), item);
-
} else if (child.toElement().tagName() == "page") {
-
parsePageElement(child.toElement(), item);
-
}
-
child = child.nextSibling();
-
}
-
}
-
void MainWindow::parsePageElement(const QDomElement &element,
-
QTreeWidgetItem *parent)
-
{
-
QString page = element.text();
-
QString allPages = parent->text(1);
-
if (!allPages.isEmpty()) {
-
allPages += ", ";
-
}
-
allPages += page;
-
parent->setText(1, allPages);
-
}
阅读(921) | 评论(0) | 转发(0) |