QT中XML的应用

Qt读取XML文档的方法

1)QXmlStreamReader:一种快速的基于流的方式访问良格式 XML 文档,特别适合于实现一次解析器(所谓“一次解析器”,可以理解成我们只需读取文档一次,然后像一个遍历器从头到尾一次性处理 XML 文档,期间不会有反复的情况,也就是不会读完第一个标签,然后读第二个,读完第二个又返回去读第一个,这是不允许的);这种方法是通过调用readNext()函数实现的,可以读取下一个记号,然后返回一个记号类型。

2)DOM(Document Object Model):将整个 XML 文档读入内存,构建成一个树结构,允许程序在树结构上向前向后移动导航,这是与另外两种方式最大的区别,也就是允许实现多次解析器(对应于前面所说的一次解析器)。DOM 方式带来的问题是需要一次性将整个 XML 文档读入内存,因此会占用很大内存。

3)SAX(Simple API for XML):提供大量虚函数,以事件的形式处理 XML 文档。应用程序必须提供处理器(回调函数) 来从解析器获得所谓XML事件。

Qt生成 XML 文档方法

1)QXmlStreamWriter与QXmlStreamReader相对应。XML流的方法
2)DOM 方式,首先在内存中生成 DOM 树,然后将 DOM 树写入文件。
3)纯手工生成 XML 文档。

Qt中QXmlStreamReader

Qt中用了两个类来读取和写入XML文档( QXmlStreamWriter与QXmlStreamReader),前面讲到过在读取XML文档时是通过readNext()函数获取下一个记号,返回的是记号
在这里插入图片描述

//QXmlStreamReader 解析文档
QFile file("../myXmlStream/my.xml");
QXmlStreamReader reader;
// 设置文件,这时会将流设置为初始状态
reader.setDevice(&file);
while (!reader.atEnd()) {
   // 读取下一个记号,它返回记号的类型
   QXmlStreamReader::TokenType type = reader.readNext();  //所有取值表17-6 P417
   // 下面便根据记号的类型来进行不同的输出
   if (type == QXmlStreamReader::StartDocument)
   if (type == QXmlStreamReader::StartElement) { //元素的起始
       if (reader.attributes().hasAttribute("id"))//如果有属性为ID的元素
   }
   if (type == QXmlStreamReader::EndElement)   //元素的截止
   if (type == QXmlStreamReader::Characters && !reader.isWhitespace()) //文本内容
}

//QXmlStreamWriter 创建文档
QFile file("../myXmlStream/my2.xml");
QXmlStreamWriter stream(&file);
//设置自动格式,会自动换行和添加缩进
stream.setAutoFormatting(true);
//自动添加首行的XML说明<?xml version="1.0" encoding="UTF-8"?>
stream.writeStartDocument();
//添加元素
stream.writeStartElement("book"); //起始元素
stream.writeAttribute("href", "http://qt.nokia.com/");
stream.writeTextElement("title", "Qt Home"); //文本元素   使用这个关闭前一个打开的元素    
stream.writeEndElement();
stream.writeEndDocument();

Qt中DOM的使用

Qt中,所有的Dom节点,比如说明,元素,属性和文本等,都使用QDomNode来表示。
文档本身用 QDomDocument 类表示。
访问XML文件

// 新建QDomDocument类对象,它代表一个XML文档
QDomDocument doc;
// 定义一个文件对象
QFile file("../myDOM1/my.xml");
//setContent()函数设置整个文档内容,将xml文档内容解析为一个DOM树
doc.setContent(&file);  
// 获得doc的第一个结点,即XML说明
QDomNode firstNode = doc.firstChild();  //若换为lastChild() 指的是根元素
// 返回根元素
QDomElement docElem = doc.documentElement();
// 返回根节点的第一个子结点
QDomNode n = docElem.firstChild();  //lastChild()获取最后一个节点  输出的是book03
// 转到下一个兄弟结点
n = n.nextSibling();  //使用previousSibling访问前一个节点
//创建XML文件
// 添加处理指令即XML说明
QDomProcessingInstruction instruction;
instruction = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");
doc.appendChild(instruction);  //添加在最后
// 添加元素
QDomElement book = doc.createElement(QString("图书"));
// 添加属性及其值
QDomAttr id = doc.createAttribute(QString("编号"));
id.setValue(QString("1"));
book.setAttributeNode(id);
//文本及其文本值
QDomText text;
text = doc.createTextNode(QString("Qt"));

Qt中SAX的使用

SAX(simple API for XML)为XML解析器提供了一个基于事件的标准接口。在Qt中支持SAX2不支持java中的SAX1。

bool readFile(const QString &fileName);//读入XML文件
//readfile设置了文件的解析过程,Qt提供了一个简单的xml解析器QXmlSimpleReader,它是基于SAX,需要QXmlInputSource为其提供数据
protected:
    //4个事件
    bool startElement(const QString &namespaceURI, const QString &localName,    //获取元素名与属性
                      const QString &qName, const QXmlAttributes &atts);
    bool endElement(const QString &namespaceURI, const QString &localName,      //结束时该元素想进行的操作
                    const QString &qName);  
    bool characters(const QString &ch);                                         //获取元素中的文本             
    bool fatalError(const QXmlParseException &exception);                       //错误处理器
//参数qName对应XML中的元素名,参数atts对应属性名,参数ch对应文本

Qt与XML的对应关系

xml中的XML说明对应QDomProcessingInstruction
xml中的元素对应QDomElement类
xml中的属性对应QDomArr类
xml中的文本内容对应QDomText类
在这里插入图片描述
QDomDocument doc;
1)创建根节点:QDomElement root = doc.createElement(“root”)
2)创建元素节点:QDomElement element = doc.createElement(“nodeName”);
3)添加元素节点到根节点:root. appendChild(element);
4)创建元素文本:QDomText nodeText=doc.createTextNode(“text”);
5)添加元素文本到元素节点:element. appendChild(nodeText);

创建一个QDomDocument类对象,代表整个XML文档

QDomDocument doc;

使用QFile打开要读取得xml文档,使用QDomDocument类的setContent()函数来设置整个文档的内容,它会将XML解析成一个DOM树,并保存在内存中

QFile file("..\\myDOM1\\my.xml");
if (!file.open (QIODevice::ReadOnly)) {
      qDebug() << "open file" << "my.xml" << "failed,error:" << file.errorString();
      return 0;
}
//将文件内容读到doc中
if (! doc.setContent(&file)) {
     qDebug() << "parse file failed at line" << errLin << ",col" << errCol << "," << strError;
     file.close ();
     return 0;
}
file.close ();

获取根节点元素,QDomDocument类也是QDomNode的子类,使用firstChild()函数可以获得它的第一个子节点

//获得doc的第一个节点,即XML说明
QDomNode firstNode = doc.firstChild ();
qDebug() << qPrintable(firstNode.nodeName()) << qPrintable(firstNode.nodeValue ());

使用documentElement()可以获得他的根节点,这是访问XML文档的入口,返回一个QDomElement的脆响,这也是QDomNode的子类

//返回根节点元素
QDomElement docElem = doc.documentElement();

后面就可以通过QDomNode来遍历整个文档
firstChild()获得第一个子节点
lastChild()获得最后一个节点
childNodes()获取该节点的所有孩子节点的一个列表
nextSibling()获取下一个兄弟节点
previousSibling()获取前一个兄弟节点.

      //返回根元素的第一个子节点
QDomNode n=docElem.firstChild ();
while (!n.isNull ()) {
    if (n.isElement ()) {
            //将其转换为元素
        QDomElement e = n.toElement ();
            //返回元素标记和id属性的值,tagName()来获取元素节点的标签名,attribute()来获取元素节点指定的属性的值,
        qDebug() << qPrintable(e.tagName ()) << qPrintable(e.attribute ("id"));
            //获得元素e的所有子节点列表
        QDomNodeList list = e.childNodes ();
        for (int i = 0; i< list.count ();i++) {
            QDomNode node = list.at(i);
            if (node.isElement ()) {//使用text()来获取其中的文本内容
                qDebug() << qPrintable(node.toElement().tagName ()) << qPrintable(node.toElement ().text ());
            }
        }
    }
    n = n.nextSibling ();//nextSibling()获取下一个兄弟节点
}

代码如下

static bool creatXml()//创建xml文件
{
    QFile file("data.xml");//创建文件
    if(file.exists())//判断是否存在
        return true;
    if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))//判断是否打开文件,用QIODevice,Truncate表示清空原来的内容

        return  false;
    QDomDocument doc;//可以访问这个对象中的每一个节点,每一个节点对应XML文件里的一个标记
    QDomProcessingInstruction instruction;
    instruction = doc.createProcessingInstruction("xml", "version = \"1.0\"encoding = \"UTF-8\"");
    doc.appendChild(instruction);//添加处理命令
    QDomElement root = doc.createElement(QString("销售清单"));//根节点
    doc.appendChild(root);//添加第一个子节点和子元素
    QTextStream out(&file);
    doc.save(out,4);//保存操作
    file.close();//关闭文件
    return true;
}

QString Sell::getDateTime(DateTimeType type)//判断需要时间类型,并返回合适的时间
{
    QDateTime datetime = QDateTime::currentDateTime();//获取现在时间
    QString date = datetime.toString("yyyy-MM-dd");
    QString time = datetime.toString("hh::mm");
    QString dateAndTime = datetime.toString("yyyy-MM-dd dddd hh:mm");
    if(type == Date)
        return  date;
    else if (type == Time)
        return  time;
    else
        return dateAndTime;
}

bool Sell::docRead()//读取xml文件
{
    QFile file("data.xml");
    if(!file.open(QIODevice::WriteOnly))//判断是否打开文件
        return false;
    if(!doc.setContent(&file))//获取文本
    {
        file.close();
        return false;
    }
    file.close();
    return true;
}
bool Sell::docWrite()//写入xml文件并保存
{
    QFile file("data.xml");
    if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))//判断是否打开文件
        return false;
    QTextStream out(&file);
    doc.save(out,4);//这里的4是缩进4格
    file.close();
    return true;
}
void Sell::writeXml()//修改xml文件
{
    if(docRead())//从文件中读取
    {
        QString currentDate = getDateTime(Date);//获取时间,类型为date
        QDomElement root = doc.documentElement();//获取根节点
        //根据是否有日期节点进行处理
        if(!root.hasChildNodes())
        {
            QDomElement date = doc.createElement(QString("日期"));//添加元素
            QDomAttr curDate = doc.createAttribute("date");//添加属性
            curDate.setValue(currentDate);//设置属性值
            date.setAttributeNode(curDate);//设置属性节点
            root.appendChild(date);//添加到根节点的子节点
        }
        else
        {
            QDomElement date = root.lastChild().toElement();
            //根据是否已经有今天的日期进行处理
            if(date.attribute("date") == currentDate)
            {
                creatNodes(date);
            }
            else
            {
                QDomElement date = doc.createElement(QString("日期"));
                QDomAttr curDate = doc.createAttribute("date");
                curDate.setValue(currentDate);
                date.setAttributeNode(curDate);
                root.appendChild(date);
                creatNodes(date);
            }
        }
    }
    docWrite();//写入文件
}
void Sell::creatNodes(QDomElement &date)//创建节点
{
    //应该需要与数据库相关联
    QDomAttr curDate = doc.createAttribute("add");
//    curDate.setValue();
    date.setAttributeNode(curDate);
    date.appendChild(curDate);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阳光开朗男孩

你的鼓励是我最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值