Qt使用SAX解析xml文件的例子

2018-05-20 22:36:40  阅读 246 次 评论 2 条

    在开始例子之前,首先了解一下SAX是什么?。

    SAX的全称是:simple API for XML,它是解析xml文件的一种方法。与之对应的另一种方法是DOM(Document Object Model)。既然两种方法都能存在,那就说明各有千秋了。SAX是一种边读取边解析的方法,由此带来的好处是它相对于DOM的解析速度更快,缺点是不容易修改xml文件。

    Qt对DOM和SAX两种解析方式都支持。这里写个sax的例子试一下。xml内容来自于网络的一个简单例子:

<bookstore>
<book category="CHILDREN">
  <title>Harry Potter</title> 
  <author>J K. Rowling</author> 
  <year>2005</year> 
  <price>29.99</price> 
</book>
<book category="WEB">
  <title>Learning XML</title> 
  <author>Erik T. Ray</author> 
  <year>2003</year> 
  <price>39.95</price> 
</book>
</bookstore>

 文件的结构一目了然,一个bookstore里有两个book,每个book都有category、title、author、year和price几个参数。(在实际开发中像这么小的文件使用DOM模型的方法更合适一些)

 

步骤:    

  1. 使用xml的模块要在pro文件中加上 QT += xml

  2. sax需要的几个对象:QXmlSimpleReader、QXmlInputSource、QXmlDefaultHandler。它们的关系可以描述为:reader读取source的内容,并使用handler来解析。所以handler是我们关注的重点,我们从QXmlDefaultHandler中派生一个处理类并重写它的处理函数实现xml文件的解析。

class Handler : public QXmlDefaultHandler
{
public:
    Handler();
protected:
    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 error(const QXmlParseException &exception);
private:
    QString        m_currentQName;
    s_Book*        m_pBook;
    QList<s_Book*> m_bookList;
};

        我们重写了startElement、endElement、characters和error几个接口分别表示遇到元素开始、元素结束、字符和错误。 s_Book是定义的book的结构体:

struct s_Book
{
    s_Book() {}
    QString _category;
    QString _title;
    QString _author;
    int     _year;
    float   _price;
};

     接着看看在四个接口中是如何来解析文件的:

bool Handler::startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts)
{
    if(qName == "bookstore"){

    }
    else if(qName == "book"){
        m_pBook = new s_Book;
        m_pBook->_category = atts.value("category");
    }
    else{
        m_currentQName = qName;
    }
    return true;
}

bool Handler::endElement(const QString &namespaceURI, const QString &localName, const QString &qName)
{
    m_currentQName = "";

    if(qName == "book"){
        m_bookList.append(m_pBook);
    }else if(qName == "bookstore"){
        for(int i = 0; i < m_bookList.count(); ++i){
            s_Book* book = m_bookList.at(i);
            QString ret("[");
            ret.append(book->_title + " : ");
            ret.append(book->_category + "    ");
            ret.append(book->_author + "   ");
            ret.append(QString::number(book->_year) + "    ");
            ret.append(QString::number(book->_price) + "]");
            qDebug()<<ret;
        }
    }

    return true;
}

bool Handler::characters(const QString &ch)
{
    if(m_currentQName == "title"){
        m_pBook->_title = ch;
    }
    else if(m_currentQName == "author"){
        m_pBook->_author = ch;
    }else if(m_currentQName == "year"){
        m_pBook->_year = ch.toInt();
    }else if(m_currentQName == "price"){
        m_pBook->_price = ch.toFloat();
    }
    return true;
}

bool Handler::error(const QXmlParseException &exception)
{
    return false;
}

当遇到book的开始元素时表示开始解析一个book的内容,此时创建一个book对象用于存储数据,当遇到book元素结束时表示当前解析的book结束了,把解析完的book对象中加入到列表中。当解析到bookstore的元素结束时表示所有内容都解析完成,此时把所有book的打印出来。

从文档上可以看出除了category是属于元素的属性以外,其他内容都属于字符,都是通过characters接口解析出来的。特别注意的一点是这几个接口返回为false时就会停止解析。

 

    3.有了reader、source和handler就可以开始解析xml文件了。

   QFile f(":/test.xml");
   QXmlInputSource source(&f);
   QXmlSimpleReader reader;
   Handler hander;
   reader.setContentHandler(&hander);
   reader.setErrorHandler(&hander);
   reader.parse(source);

    reader设置好handler后调用parse解析source整个过程就结束了,就是这么简单。


    4.输出结果:

"[Harry Potter : CHILDREN    J K. Rowling   2005    29.99]"

"[Learning XML : WEB    Erik T. Ray   2003    39.95]"


本文地址:http://fearlazy.com/index.php/post/75.html
版权声明:本文为原创文章,版权归 fearlazy 所有,欢迎分享本文,转载请保留出处!
NEXT:已经是最新一篇了

发表评论


表情

评论列表

  1. www.suchunyu.com
    www.suchunyu.com  @回复

    文章写得太好了,赞一个!

  2. www.mjquan.com
    www.mjquan.com  @回复

    学习了,写的很不错