XML ,全称为 可扩展标记语言 ”(extensible markup language). 是一种非常方便的 数据交换 数据存储 的工具。

我们在取得一个 XML 格式的文件后,需要作句法分析去提取发布方提供的信息。而 Qt XML 提供了很好的支持,包括 DOM 方式的实现和 SAX 方式的实现。

二者主要区别是:

DOM ( Document Object Model ) 实现方式操作非常简单,但不适合处理过大文件;而 SAX 实现方式是能处理很大的 XML 文件,但是需要开发者写一些复杂的代码。 Qt 提供了对应于这两种用于 读取、操作和编写 XML 的实现类,分别是 QDomDocument 类和 QXmlStreamReader ,这里我们选 QDomDocument 来处理 XML 文件。

首先是读取 XML

主要操作包括:

1). 读取根节点: QDomElement root = doc.documentElement();

2). 读取第一个子节点: QDomNode node = root.firstChild();

3). 读取下一个子节点: node = node.nextSibling();

4). 匹配结点标记: node.toElement().tagName() == "note"

5). 读取节点文本: no = childNode.toText().data();

QFile file(fileName);
if (!file.open(QFile::ReadOnly | QFile::Text)) {
return false ;
}
QString errorStr;
int errorLine;
int errorColumn;

QDomDocument doc;
if (!doc.setContent(&file, false , &errorStr, &errorLine, &errorColumn))

{ // setContent 是将指定的内容指定给 QDomDocument 解析,第一参数可以是 QByteArray 或者是文件名等。
return false ;
}

file.close();

可以通过 doc.childNodes() 获得 doc 的所有的 子节点 列表 QDomNodeList 。比如

QDomNodeList list=doc.childNodes();

for(int i=0;i<list.count();i++)

QDomNode node=list.at(i);

// qDebug()<<”node name is “<<node.nodeName();

// qDebug()<<”node type is “<< node .nodeType();

通过上面的方法你就能知道 每个节点的 名字和类型 了, 节点名字就是 标记 的名字 。打印出来对照着 xml 文件看就很容易明白了。 QDomNode 类是一个父类 , QDomDocument QDomNode 的一个子类 ,鉴于大部分 QDomNode 的类型 都是 QDomDocument. 那么你可以使用 toDocument() 函数将 QDomNode 类型转换成 QDomDocument.

QString text=node.toElement().text();

上面的语句可以将一个 节点里的 文本 取出 也就是 标记内的文本 部分 。使用该函数获得的编码就已经是 unicode 格式了,不需要再做转换。

然后是写入 XML

创建节点,将其写入 XML 文件,主要操作包括:

1). 创建根节点: QDomElement root = doc.documentElement("rootName " );

2). 创建元素节点: QDomElement element = doc.createElement_x_x_x("nodeName");

3). 添加 元素节点 根节点: root. a(element);

4). 创建文本节点: QDomText nodeText=doc.createTextNode("text");

5). 添加 文本节点 元素节点: element. a(nodeText);

XML 文件的内容:

<?xml version="1.0" encoding="UTF-8"?>

<Notes>

<no>001</no>

<name>2010-05-10(13:53:24)</name>

<content>A meeting </content>

<font>Script MT Bold</font>

</note>

</Notes>

QFile  file(fileName);
if (!file.open(QFile::ReadOnly | QFile::Text))
return false ;
QString errorStr;
int errorLine;
int errorColumn;
QDomDocument doc;
if (!doc.setContent(&file, false , &errorStr, &errorLine, &errorColumn))
return false ;

file.close();

QDomElement root = doc.documentElement();
if (root.tagName() != "root" )
return false ;

QDomElement element =   doc.createElement_x_x_x(
"file" );


QDomElement el_address = doc.createElement_x_x_x(
"address" );
QDomText text_address = doc.createTextNode(
"text" );


el_address. a
(text_address);
element.
a
(el_address);

QDomElement el_path = doc.createElement_x_x_x_x( "path" );
QDomText text_path = doc.createTextNode(
"text" );


el_path. a (text_path);
element.
a
(el_path);

root.
a
(element);

QFile f(fileName);
if (!f.open(QFile::WriteOnly | QFile::Text))
return false ;

QTextStream out (&f);

out.setCodec("UTF-8"); // 中文编码

// doc.save(out,4,QDomNode::EncodingFromTextStream);

doc.save(out, 3);
f.close();

这里 所有需要 append 的字节点只能由 QDomDocument 对象 create ,而 不能直接 new ,否则永远也看不到新添加的节点,另外, 读取和写入的文件流必须创建两个 ,否则会将需要写入的文档继续在原来文档的后面,造成多个根节点。