Qt Gui 第十六章

一、QXmlStreamReader

用于读取格式良好的xml文档的快速解析器;解析步骤

QXmlStreamReader reader;
QFile file(fileName);
reader.setDevice(&file);

如上将xml文件加载到reader中;也可以直接 QXmlStreamReader reader(&file); 

接下去可以遍历xml节点;通过 reader.readNext(); 顺序遍历每一个节点;返回的类型可以有

复制代码
        Invalid,
        StartDocument,
        EndDocument,
        StartElement,
        EndElement,
        Characters,
        Comment,
        DTD,
        EntityReference,
        ProcessingInstruction
复制代码

也可以通过判断是否是自己想要的类型如: reader.atEnd()、reader.isEndElement()、reader.isStartElement()等类型判断是否到自己想要的位置;atEnd是指当前层的节点已经遍历完了;isEndElement是指当前节点已经遍历了(主要是指子节点也遍历完了)

reader.name()获取到当前节点的名字;reader.attributes().value("term").toString()获取指定属性的值,如term属性的值;reader.readElementText()则是读取节点的text;

例如读取如下的xml数据:

<entry term="sidebearings">
        <page>10</page>
</entry>

1、readNext读取到<entry term="sidebearings">;然后通过reader.attributes().value("term").toString()则会返回sidebearings;

2、readNext读取到“\n        ”这里我用双引号标出来;则readNext返回的type是Characters

3、readNext读取到的是<page>10</page>;然后通过reader.readElementText()读取到10这个字符串;

4、readNext读取到“\n”,readNext返回的type是Characters

5、readNext读取到的是</entry>;readNext返回的类型是EndElement

6、readNext读取到“”,其实啥都没有读取到,返回的类型是EndElement,但是atEnd标记的是true;(这里不管读到的是还有其他字符与否,atEnd都直接标记true)

 

二、DOM

是一种解析由万维网协会(W3C)所开发的xml文档的标准应用程序编程接口。

复制代码
QDomDocument doc;
doc.setContent(&file, false, &errorStr, &errorLine, &errorColumn);
QDomElement root = doc.documentElement();
QDomNode child = root.firstChild();
//然后遍历当前层的所有孩子
    while (!child.isNull()) {
        if (child.toElement().tagName() == "entry")
            parseEntryElement(child.toElement(),treeWidget->invisibleRootItem());
        child = child.nextSibling();
    }
复制代码

1、声明一个文档的dom:doc

2、然后doc.setContent则是解析了整个xml文件;接下去无需再读取文件的操作。

3、获取doc的QDomElement,即获取xml的第一层的element

4、然后获取root.firstChild()获取第一层element的子节点,将子节点当成一个node;当要查找下一个兄弟节点,则是 child.nextSibling();

5、将node抓换成element

。。。。然后遍历递归所有子节点;

element.attribute("term")获取属性term的值;如果有多个属性的时候,可以通过

    QDomNamedNodeMap node_map = element.attributes();
    for (int i = 0; i < node_map.count(); ++i) {
        QDomNode node = node_map.item(i);
        QDomAttr atr = node.toAttr();
        atr.value();
        atr.name();
    }


获取所有的属性,然后遍历所有的属性;也可以通过node_map.namedItem(const QString& name)来获取对应的QDomNode

要获取对应的标签名字:child.toElement().tagName()

 

三、QXmlDefaultHandler

该函数是通过继承来处理自己想要读取的节点的信息;

复制代码
class Q_XML_EXPORT QXmlDefaultHandler : public QXmlContentHandler, public QXmlErrorHandler, public QXmlDTDHandler, public QXmlEntityResolver, public QXmlLexicalHandler, public QXmlDeclHandler
{
public:
    QXmlDefaultHandler() { }
    virtual ~QXmlDefaultHandler() { }

    void setDocumentLocator(QXmlLocator* locator);
    bool startDocument();
    bool endDocument();
    bool startPrefixMapping(const QString& prefix, const QString& uri);
    bool endPrefixMapping(const QString& prefix);
    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 ignorableWhitespace(const QString& ch);
    bool processingInstruction(const QString& target, const QString& data);
    bool skippedEntity(const QString& name);

    bool warning(const QXmlParseException& exception);
    bool error(const QXmlParseException& exception);
    bool fatalError(const QXmlParseException& exception);

    bool notationDecl(const QString& name, const QString& publicId, const QString& systemId);
    bool unparsedEntityDecl(const QString& name, const QString& publicId, const QString& systemId, const QString& notationName);

    bool resolveEntity(const QString& publicId, const QString& systemId, QXmlInputSource*& ret);

    bool startDTD(const QString& name, const QString& publicId, const QString& systemId);
    bool endDTD();
    bool startEntity(const QString& name);
    bool endEntity(const QString& name);
    bool startCDATA();
    bool endCDATA();
    bool comment(const QString& ch);

    bool attributeDecl(const QString& eName, const QString& aName, const QString& type, const QString& valueDefault, const QString& value);
    bool internalEntityDecl(const QString& name, const QString& value);
    bool externalEntityDecl(const QString& name, const QString& publicId, const QString& systemId);

    QString errorString() const;

private:
    QXmlDefaultHandlerPrivate *d;
    Q_DISABLE_COPY(QXmlDefaultHandler)
};
View Code
复制代码

如上的QXmlDefaultHandler头文件代码所示,看自己需要的信息是什么,通过继承对应的函数来获取;

举个例子:

假设子类继承了QXmlDefaultHandler的四个函数,如下

复制代码
    bool startElement(const QString &namespaceURI,
                      const QString &localName,
                      const QString &qName,
                      const QXmlAttributes &attributes);
    bool endElement(const QString &namespaceURI,
                    const QString &localName,
                    const QString &qName);
    bool characters(const QString &str);
    bool fatalError(const QXmlParseException &exception);
复制代码

然后实现自定义的函数readFile

复制代码
bool SaxHandler::readFile(const QString &fileName)
{
    currentItem = 0;

    QFile file(fileName);
    QXmlInputSource inputSource(&file);
    QXmlSimpleReader reader;
    reader.setContentHandler(this);
    reader.setErrorHandler(this);
    return reader.parse(inputSource);
}
复制代码

这里的reader有两个setXXXHandler,那是因为我们重新实现了对应的Content类里面的函数startElement、endElement、characters;对应的Error类里面的fatalError函数;查看具体用到哪些类的函数,可以看QXmlDefaultHandler所在的头文件;

 

posted @   LCAC  阅读(214)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
点击右上角即可分享
微信分享提示