Qt之XML(DOM)

简介: 简述DOM(Document Object Model - 文档对象模型)定义了访问和操作 XML 文档的标准方法。DOM 把 XML 文档作为树结构来查看,能够通过 DOM 树来访问所有元素。可以修改或删除它们的内容,并创建新的元素。元素及其文本、属性都被认为是节点。简述详细说明使用生成解析更多参考详细说明QDomDo

简述

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() 函数均可。

更多参考

目录
相关文章
|
1天前
|
XML JavaScript 前端开发
XML DOM 节点信息
XML DOM 节点详解:nodeName、nodeValue 和 nodeType 属性用于获取和操作节点信息。示例展示如何加载XML文件,如books.xml,通过loadXMLDoc函数。nodeName获取元素节点名,nodeValue用于获取或设置文本节点内容,nodeType显示节点类型(如元素:1,属性:2,文本:3,注释:8,文档:9)。每个节点都是可访问和操作的对象,包含方法和属性。
|
1天前
|
XML JavaScript 前端开发
XML DOM 节点信息
XML DOM中的每个节点都是一个具有方法和属性的对象,可通过JavaScript操作。关键属性有:nodeName(定义节点名称,如元素、属性或#text)、nodeValue(提供节点值,如文本或属性值)和nodeType。元素节点的nodeName等于标签名,属性节点的nodeName是属性名。文本节点的nodeValue是其文本内容,而文档节点的nodeName是&quot;#document&quot;。示例代码演示了如何获取第一个&lt;title&gt;元素的文本值。
|
2天前
|
XML 存储 JavaScript
XML DOM - 访问节点
使用DOM,可以访问XML文档的每个节点。访问方法包括:通过getElementsByTagName(),遍历节点树和导航节点关系。getElementsByTagName()返回一个Node List,它是节点数组,可用于按索引访问元素,如`x[2]`获取第三个&lt;title&gt;元素。后续章节将进一步探讨Node List。
|
3天前
|
XML JavaScript 数据格式
XML DOM - 访问节点
XML DOM 允许访问每个文档节点。方法包括:`getElementsByTagName()`用于获取指定标签的元素;遍历节点树;及导航节点关系。例如,`getElementsByTagName(&quot;title&quot;)`返回所有`&lt;title&gt;`元素。在示例中,`x.getElementsByTagName(&quot;title&quot;)`找到`x`下的`&lt;title&gt;`,而`xmlDoc.getElementsByTagName(&quot;title&quot;)`则查找整个文档的`&lt;title&gt;`元素。
|
3天前
|
XML JavaScript 前端开发
XML DOM - 属性和方法
XML DOM 提供编程接口,让开发者用JavaScript等语言操作XML文档。接口包含属性和方法,属性如nodeName、nodeValue、parentNode和childNodes,用于查询节点信息;方法如getElementsByTagName、appendChild和removeChild,执行增删操作。示例中,JavaScript代码`txt=xmlDoc.getElementsByTagName(&quot;title&quot;)[0].childNodes[0].nodeValue`从books.xml获取第一个&lt;title&gt;元素的文本内容,赋值给变量txt。
|
4天前
|
XML 存储 JavaScript
XML DOM 加载函数
`loadXMLString()`函数被封装在名为&quot;loadxmlstring.js&quot;的外部JavaScript文件中,用于加载XML文档。在示例HTML中,这个函数被调用来处理动态生成的XML字符串,该字符串描述了一本名为&quot;Everyday Italian&quot;的书籍信息。之后,可以在`code goes here.....`处进一步处理`xmlDoc`对象。
|
4天前
|
XML 存储 JavaScript
XML DOM 加载函数
`loadXMLDoc()` 是一个JavaScript函数,用于加载XML文档。它支持XMLHttpRequest和ActiveXObject,适应不同浏览器。函数定义存储在名为`loadxmldoc.js`的外部文件中,包含在HTML `&lt;head&gt;`标签内,然后在页面脚本中调用来获取XML数据,如`books.xml`。接下来的章节将介绍如何处理加载的数据。
|
7天前
|
XML Web App开发 JavaScript
XML DOM 解析器
大多数浏览器内置XML解析器,用于将XML转换为JavaScript可操作的DOM对象。解析器提供遍历、修改XML节点的功能。以下JS代码示例展示了如何加载XML文档:&quot;books.xml&quot;,通过XMLHttpRequest或ActiveXObject发送请求,获取响应并转化为DOM对象。
|
7天前
|
XML JavaScript 数据格式
XML DOM 节点树
在XML文档中最后一个。
|
7天前
|
XML JavaScript 数据格式
XML DOM 节点树
**XML DOM**将XML文档建模为节点树,其中每个组件都是节点,相关联并可操作。树有根节点,扩展至包含子节点和文本节点的分支。节点间关系包括父-子和同级。根节点居首,每个非根节点有唯一父节点,可有多个子节点,叶子节点无子节点,同级节点共享父节点。通过DOM可访问、修改、创建和删除节点。