Qt之XML(DOM)

简述

DOM(Document Object Model - 文档对象模型)定义了访问和操作 XML 文档的标准方法。

DOM 把 XML 文档作为树结构来查看,能够通过 DOM 树来访问所有元素。可以修改或删除它们的内容,并创建新的元素。元素及其文本、属性都被认为是节点。

  • 简述
  • 详细说明
  • 使用
    • 生成
    • 解析
  • 更多参考

详细说明

QDomDocument 类表示一个 XML 文档。

QDomDocument 类表示整个 XML 文档。从概念上讲,它是文档树的根,并提供对文档数据的主要访问。

因为元素、文本节点、注释、处理指令等不能存在于文档的上下文之外,所以文档类还包含创建这些对象所需的工厂函数。创建的节点对象有一个 ownerDocument() 函数,将它们与在其上下文中创建的文档相关联。最常用的 DOM 类是 QDomNode、QDomDocument、QDomElement 和 QDomText。

解析的 XML 在内部由对象树表示,可以使用各种 QDom 类访问,所有的 QDom 类只引用内部树中的对象。一旦最后一个 QDom 对象引用它们或 QDomDocument 本身被删除,DOM 树中的内部对象将被删除。

元素、文本节点等的创建使用此类中提供的各种工厂函数完成。使用 QDom 类的默认构造函数只会导致无法操作或插入到 Document 中的空对象。

QDomDocument 类具有创建文档数据的多个函数,例如:createElement()、createTextNode()、createComment()、createCDATASection()、createProcessingInstruction()、createAttribute() 和 createEntityReference()。这些函数中的一些具有支持命名空间的版本,即:createElementNS() 和 createAttributeNS()。createDocumentFragment() 函数用于保存文档的各部分,这对于处理复杂文档很有用。

文档的整个内容使用 setContent() 设置。此函数解析的字符串,作为一个 XML 文档以及创建表示文档的 DOM 树传递。根元素可以使用 documentElement() 来获取,文档的文本表示可以使用 toString() 获取。

注意:如果 XML 文档较大,DOM 树可能最终会保留大量内存。对于这样的文档,QXmlStreamReader 或 QXmlQuery 类可能是更好的解决方案。

可以使用 importNode() 将来自另一个文档的节点插入到文档中。

可以根据 elementsByTagName() 或 elementsByTagNameNS() 获取具有特定标记的所有元素的列表。

使用

为了便于演示,使用上节生成的格式化 XML(Blogs.xml):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--纯正开源之美,有趣、好玩、靠谱。。。-->
<?xml-stylesheet type="text/css" href="style.css"?>
<Blogs Version="1.0">
 <Blog>
  <作者>一去丶二三里</作者>
  <主页>http://blog.csdn.net/liang19890820</主页>
  <个人说明>青春不老,奋斗不止!</个人说明>
 </Blog>
</Blogs>

详细说明见: Qt之生成XML(QXmlStreamWriter)

生成

函数 writeXML() 主要用于生成 XML,将生成的内容写入 Blogs.xml 文件中:

void writeXML() {
    QDomDocument doc;

    QDomProcessingInstruction xmlInstruction = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"");
    QDomComment comment = doc.createComment(QString::fromLocal8Bit("纯正开源之美,有趣、好玩、靠谱。。。"));
    QDomProcessingInstruction styleInstruction = doc.createProcessingInstruction("xml-stylesheet", "type=\"text/css\" href=\"style.css\"");
    doc.appendChild(xmlInstruction);  // 开始文档(XML 声明)
    doc.appendChild(comment);  // 注释
    doc.appendChild(styleInstruction);  // 处理指令

    // 根元素 <Blogs>
    QDomElement root = doc.createElement("Blogs");
    root.setAttribute("Version", "1.0");  // 属性
    doc.appendChild(root);

    // 元素 <Blog>
    QDomElement child = doc.createElement("Blog");
    root.appendChild(child);

    // 元素 <作者>、<主页>、<个人说明>
    QDomElement author = doc.createElement(QString::fromLocal8Bit("作者"));
    QDomElement home = doc.createElement(QString::fromLocal8Bit("主页"));
    QDomElement instruction = doc.createElement(QString::fromLocal8Bit("个人说明"));
    child.appendChild(author);
    child.appendChild(home);
    child.appendChild(instruction);

    // 元素的文本数据
    QDomText authorText = doc.createTextNode(QString::fromLocal8Bit("一去丶二三里"));
    QDomText homeText = doc.createTextNode("http://blog.csdn.net/liang19890820");
    QDomText instructionText = doc.createTextNode(QString::fromLocal8Bit("青春不老,奋斗不止!"));
    author.appendChild(authorText);
    home.appendChild(homeText);
    instruction.appendChild(instructionText);

    // 保存 XML 文件
    QString strFile("Blogs.xml");
    QFile file(strFile);
    if (file.open(QFile::WriteOnly | QFile::Text)) { // 只写模式打开文件
        QTextStream out(&file);
        doc.save(out, QDomNode::EncodingFromDocument);
        file.close();
    }
}

首先,根据 QDomDocument 构造一个 DOM 文档。通过调用其工厂方法 create…() 创建对应的节点,然后利用 appendChild() 进行添加,进而构建一个对象树。

解析

函数 readXML() 主要用于解析 XML,将 Blogs.xml 文件中的内容解析为节点:

void readXML() {
    QDomDocument doc;
    QFile file("Blogs.xml");
    if (!file.open(QIODevice::ReadOnly))
        return;
    if (!doc.setContent(&file)) {
        file.close();
        return;
    }
    file.close();

    /**********根元素 <Blogs>**********/
    QDomElement root = doc.documentElement();
    qDebug() << root.tagName();

    if (root.hasAttribute("Version"))  // 属性
        qDebug() << root.attribute("Version");

    /**********根元素之上(XML 声明、注释等)**********/
    QDomNode node = root.previousSibling();
    while (!node.isNull()) {
        switch (node.nodeType()) {
        case QDomNode::ProcessingInstructionNode : {
            QDomProcessingInstruction instruction = node.toProcessingInstruction();
            qDebug() << instruction.target() << instruction.data();
            if (QString::compare(instruction.target(), "xml") == 0) { // 开始文档(XML 声明)
                // ...
            } else if (QString::compare(instruction.target(), "xml-stylesheet") == 0) { // 处理指令
                // ...
            }
            break;
        }
        case QDomNode::CommentNode : {
            QDomComment comment = node.toComment();
            qDebug() << comment.data();
            break;
        }
        default:
            break;
        }
        node = node.previousSibling();
    }

    /**********元素 <Blog>**********/
    node = root.firstChild();  // 返回根节点的第一个子节点
    while (!node.isNull()) {
        if (node.isElement()) {
            QDomElement element = node.toElement();  // 尝试将节点转换为元素
            if (!element.isNull()) {  // 节点的确是一个元素
                qDebug() << element.tagName();

                /**********遍历元素 <作者>、<主页>、<个人说明>**********/
                QDomNodeList list = element.childNodes();
                for (int i = 0; i < list.count(); i++) {
                    node = list.at(i);
                    if (node.isElement()) {
                        element = node.toElement();
                        qDebug() << element.tagName() << element.text();
                        if (QString::compare(element.tagName(), QStringLiteral("作者")) == 0) {
                            // ...
                        } else if (QString::compare(element.tagName(), QStringLiteral("主页")) == 0) {
                            // ...
                        } else if (QString::compare(element.tagName(), QStringLiteral("个人说明")) == 0) {
                            // ...
                        }
                    }
                }
            }
        }
        node = node.nextSibling();
    }
}

和 XML 的生成类似,读取是写入的逆过程。读取的入口根据 QDomDocument 调用 documentElement() 返回的根元素。通过根元素,可以获取到任何我们想要的节点,例如:通过 previousSibling() 向上查找兄弟节点;同理,也可以调用 nextSibling() 向下查找。示例中,我们使用 while() 循环,利用 nextSibling() 反复查找根节点 <Blogs>下的所有 <Blog> 子节点 。在读取 <Blog> 的过程中,通过 childNodes() 返回其下的所有节点,然后进行遍历,tagName() 返回标签的名称,text() 则返回相应的内容。

注意:进行解析的时候,尽可能的判断节点的类型,通过调用 nodeType() 或者 isElement() 函数均可。

更多参考

时间: 2016-10-31

Qt之XML(DOM)的相关文章

Qt之XML

简述 XML(EXtensible Markup Language - 可扩展标记语言)是一种用于记录多种数据类型的标记语言.使用 XML 可以将各类型的文档定义为容易读取的格式,便于用户读取.而且,在应用程序中使用 XML,可以轻松实现数据交换. 简述 使用 XML 模块 XML 的访问方式 DOM SAX SAX2 介绍 XML 流 QXmlStreamReader QXmlStreamWriter 使用哪种方式 更多参考 使用 XML 模块 要链接到 XML 模块,需要在 qmake 项目

Qt之XML(SAX)

简述 SAX(Simple API for XML)是用于 XML 解析器的基于事件的标准接口.XML 类的设计遵循 SAX2 Java interface,名称适合 Qt 的命名约定.对于任何使用 SAX2 的人来说,使用 Qt XML 类应该非常容易. SAX 不同于 DOM 解析,它逐行扫描文档,一边扫描一边解析.由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中,这对于大型文档的解析是个巨大优势. Qt XML 模块提供了一个抽象类 QXmlReader,它定义了潜在的

IE中的XML DOM

dom|xml 当微软在IE 5.0中第一次加入对XML支持时,他们只是在MSXML ActiveX库(最初是为了在IE 4.0中解析Active Channels的组件)中实现XML的功能.最初的版本并没有打算公开使用,然而随着开发人员逐渐了解这个组件并尝试使用时,微软才意识到这个库的重要性,很快就在IE 4.01中发布了MSXML完全升级版本.MSXML最初还只是IE的一个组件.直到2001年,微软发布了MSXML 3.0,这是一个通过其公司网站独立发布的产品.在2001年晚些时候,微软又发

用PHP读取和编写XML DOM的实现代码

用 PHP 读取和编写可扩展标记语言(XML)看起来可能有点恐怖.实际上,XML 和它的所有相关技术可能是恐怖的,但是用 PHP 读取和编写 XML 不一定是项恐怖的任务.首先,需要学习一点关于 XML 的知识 -- 它是什么,用它做什么.然后,需要学习如何用 PHP 读取和编写 XML,而有许多种方式可以做这件事. 本文提供了 XML 的简短入门,然后解释如何用 PHP 读取和编写 XML. 什么是 XML? XML 是一种数据存储格式.它没有定义保存什么数据,也没有定义数据的格式.XML 只

用PHP读取和编写XML DOM

dom|xml     有许多技术可用于用 PHP 读取和编写 XML.本文提供了三种方法读取 XML:使用 DOM 库.使用 SAX 解析器和使用正则表达式.还介绍了使用 DOM 和 PHP 文本模板编写 XML. 用 PHP 读取和编写可扩展标记语言(XML)看起来可能有点恐怖.实际上,XML 和它的所有相关技术可能是恐怖的,但是用 PHP 读取和编写 XML 不一定是项恐怖的任务.首先,需要学习一点关于 XML 的知识 -- 它是什么,用它做什么.然后,需要学习如何用 PHP 读取和编写

构建自己的轻量级XML DOM分析程序

dom|xml|程序 XML正迅快速的成为数据存储和交换的标准格式流行开来了.现在可用的完整的Java XML分析器非常庞大而且功能强大--但是实现这些强大的功能的同时也要消耗等量的资源.举例来说,流行的Apache Xerces-J分析器超过1.7 MB,而最新的完整的Sun JAXP(用于XML处理的Java应用编程接口)实现程序包超过了3MB.因此使用一个功能强大的XML分析器可能过于浪费.如果配置环境是一个Java小程序或者是一个J2ME应用程序,网络带宽或者系统存储器的制约可能根本不能

使用XML DOM生成XML(1)

dom|xml|生成xml  <--编者按:随着 XML 在网络开发中的应用的不断深入,该语言的复杂度在增加,你可以在本文对XML的新对象库XML DOM的介绍中体会到这一点-->      正如你所了解的,XML是个功能强大的新型数据结构,它可以让你把网页的内容和表现形式分开.尽管如此,目前,我们的文章大多仅介绍了直接生成XML标记得的法.我们在大多数时候,都是手工编写必需的标记和数据的.      幸运的是,微软提供了XML DOM(XML文档对象模型),这是另外一种编写XML代码的方法.

使用XML DOM生成XML(3)

dom|xml|生成xml 对结点的属性赋值   一旦创建了结点,还要对其属性赋值,如独立的标识符,或者特性值.你要用到SetAttribute方法.该方法接收两个参数- 属性名和属性值.例如,下列代码创建了属性名SHIPPING_DATASOURCE 和属性值NORTH_ATLANTIC_SHIPPING:      objXMLroot.SetAttribute _       "SHIPPING_DATASOURCE", _       "NORTH_ATLANTIC_

使用XML DOM生成XML(2)

dom|xml|生成xml 创建结点      XMLDOMDocument 对象提供了创建结点或者XMLDOMNode的两种方法: CreateElement 和CreateNode.选择其中哪一种方法,取决于你需要结点提供信息量的多少.当你使用CreateElement 方法时,只要提供结点名称,如      Set objXMLroot = objXMLdoc _       .CreateElement("ORDER_STATUS")      当使用CreateNode 方法