Qt之XML(DOM)

前端之家收集整理的这篇文章主要介绍了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"?>@H_403_57@
<!--纯正开源之美,有趣、好玩、靠谱。。。-->@H_403_57@
<?xml-stylesheet type="text/css" href="style.css"?>@H_403_57@
<Blogs@H_403_57@ Version@H_403_57@="1.0"@H_403_57@>@H_403_57@
 <Blog@H_403_57@>@H_403_57@
  <作者@H_403_57@>@H_403_57@一去丶二三里</作者@H_403_57@>@H_403_57@
  <主页@H_403_57@>@H_403_57@http://blog.csdn.net/liang19890820</主页@H_403_57@>@H_403_57@
  <个人说明@H_403_57@>@H_403_57@青春不老,奋斗不止!</个人说明@H_403_57@>@H_403_57@
 </Blog@H_403_57@>@H_403_57@
</Blogs@H_403_57@>@H_403_57@

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

生成

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

void writeXML() {
    QDomDocument doc;@H_403_57@

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

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

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

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

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

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

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

解析

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

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

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

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

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

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

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

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

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

更多参考

猜你在找的XML相关文章