QtXml:QDomDocument

一、描述

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

由于元素、文本节点、注释、处理指令等不能存在于文档的上下文之外,因此文档类还包含创建这些对象所需的工厂函数。创建的节点对象有一个 ownerDocument() 函数,该函数将它们与创建它们的上下文中的文档相关联。

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

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

注意:如果 XML 文档很大,DOM 树最终可能会消耗大量内存。对于此类文档,QXmlStreamReader 类可能是更好的解决方案。

QDom 类通常如下使用:

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

QDomElement docElem = doc.documentElement();

QDomNode n = docElem.firstChild();
while(!n.isNull()) 
{
    QDomElement e = n.toElement();
    if(!e.isNull())
    {
        cout << qPrintable(e.tagName()) << '\n';
    }
    n = n.nextSibling();
}

QDomElement elem = doc.createElement("img");
elem.setAttribute("src", "myimage.png");
docElem.appendChild(elem);

要使用 DOM 创建文档,请使用如下代码:

    QDomDocument doc("mydocument");
    QDomElement root = doc.createElement("MyML");
    doc.appendChild(root);

    QDomElement tag = doc.createElement("Greeting");
    root.appendChild(tag);

    QDomText t = doc.createTextNode("Hello World");
    tag.appendChild(t);

//    QString xml = doc.toString();
    QFile file("demo.xml");
    file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
    QTextStream out(&file);
    out.setCodec("UTF-8");
    doc.save(out, 4, QDomNode::EncodingFromTextStream);
    file.close();

 

二、成员函数

1、QDomDocument(const QDomDocument&x)

拷贝构造。副本的数据是共享的(浅拷贝),修改文档的一个节点另一个文档也会改变。

2、QDomDocument(const QDomDocumentType doctype)

根据类型创建文档。

 3、QDomDocument(const QString &name)

创建文档并将文档类型的名称设置为 name。

4、QDomDocument & operator=(const QDomDocument &x)

赋值操作。浅拷贝。

5、QDomAttr createAttribute(const QString &name)

创建名为 name 的新属性,该属性可以使用 QDomElement::setAttributeNode()插入到元素中。

如果name不是有效的XML名称,则此函数的行为由QDomImplementation::InvalidDataPolicy 控制。

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

    QDomElement docElem = doc.documentElement();
    QDomAttr node = doc.createAttribute("test");
    node.setValue("666");
    docElem.setAttributeNode(node);

    file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
    QTextStream out(&file);
    out.setCodec("UTF-8");
    doc.save(out, 4, QDomNode::EncodingFromTextStream);
    file.close();

 

6、QDomAttr createAttributeNS(const QString &nsURI, const QString &qName)

创建具有命名空间支持的新属性,该属性可以插入到元素中。 属性的名称是 qName,命名空间 URI 是 nsURI。 

如果name不是有效的XML名称,则此函数的行为由QDomImplementation::InvalidDataPolicy 控制。

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

    QDomElement docElem = doc.documentElement();
    auto nsattr = doc.createAttributeNS("url1", "p:at");//命名空间url1
    docElem.setAttributeNodeNS(nsattr);

    file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
    QTextStream out(&file);
    out.setCodec("UTF-8");
    doc.save(out, 4, QDomNode::EncodingFromTextStream);
    file.close();

    auto nsattr = doc.createAttributeNS("url1", "p:at");//命名空间url1
    nsattr.setValue("111");
    docElem.setAttributeNodeNS(nsattr);

 

参考:

XML 命名空间 

避免混合使用NS和非NS版本的DOM API

7、QDomCDATASection createCDATASection(const QString &value)

创建一个新的 CDATA 部分。

如果 value 包含不能存储在 CDATA 部分中的字符,则此函数的行为由 QDomImplementation::InvalidDataPolicy 控制。

    QDomCDATASection node = doc.createCDATASection(QObject::tr("This is a comment"));
    docElem.insertBefore(node,docElem.firstChild());

8、QDomComment createComment(const QString &value)

创建注释。

如果 value 包含不能存储在 XML 注释中的字符,则此函数的行为由 QDomImplementation::InvalidDataPolicy 控制。

    QDomElement docElem = doc.documentElement();
    QDomComment node = doc.createComment(QObject::tr("This is a comment"));
    docElem.insertBefore(node,docElem.firstChild());

9、QDomDocumentFragment createDocumentFragment()

创建一个新的文档片段,可用于保存文档的一部分。

    QDomElement docElem = doc.documentElement();
    QDomComment node = doc.createComment(QObject::tr("This is a comment"));
    docElem.insertBefore(node,docElem.firstChild());
    
    QDomDocumentFragment fragNode = doc.createDocumentFragment();
    fragNode.appendChild(doc.createComment(QObject::tr("This is a Fragment comment")));
    docElem.insertBefore(fragNode,docElem.firstChild());

10、QDomElement createElement(const QString &tagName)

创建一个名为 tagName 的新元素,它可以插入到 DOM 树中。

如果 tagName 不是有效的 XML 名称,则此函数的行为由 QDomImplementation::InvalidDataPolicy 控制。

    QDomElement docElem = doc.documentElement();
    QDomElement node = doc.createElement("elementNode");
    docElem.appendChild(node);

 11、QDomElement createElementNS(const QString &nsURI, const QString &qName)

创建一个具有命名空间支持的新元素,可以插入到 DOM 树中。 元素的名称是 qName,命名空间 URI 是 nsURI。

如果 qName 为空字符串,则无论是否设置了无效数据策略,都返回空元素。

    QDomElement docElem = doc.documentElement();
    QDomElement ElementNSNode = doc.createElementNS("url1", "p:at");
    ElementNSNode.setTagName("xxx");
    ElementNSNode.setAttributeNS("url1", "p:at","666");
    docElem.appendChild(ElementNSNode);

12、QDomEntityReference createEntityReference(const QString &name)

创建一个名为 name 的新实体引用,可以插入到文档中。

如果 name 不是有效的 XML 名称,则此函数的行为由 QDomImplementation::InvalidDataPolicy 控制。

    QDomElement docElem = doc.documentElement();
    QDomEntityReference  node = doc.createEntityReference("well");
    docElem.appendChild(node);

13、QDomProcessingInstruction createProcessingInstruction(const QString &target, const QString &data)

创建可以插入文档的新处理指令。该函数将处理指令的目标设置为target,将数据设置为data。

如果目标不是有效的 XML 名称,或者数据如果包含不能出现在处理指令中的字符,则此函数的行为由 QDomImplementation::InvalidDataPolicy 控制。

可参考:XML DOM - ProcessingInstruction 对象

14、QDomText createTextNode(const QString &value)

创建一个文本节点。

如果 value 包含不能存储为 XML 文档的字符数据的字符(即使以字符引用的形式),则此函数的行为由 QDomImplementation::InvalidDataPolicy 控制。

    QDomElement docElem = doc.documentElement();
    auto node = doc.createTextNode("well");
    docElem.appendChild(node);

15、QDomDocumentType doctype()

返回此文档的文档类型。

16、QDomElement documentElement()

返回文档的根元素。

17、QDomNodeList elementsByTagName(const QString &tagname)

返回一个 QDomNodeList,它包含文档中名称为 tagname 的所有元素。节点列表的顺序是它们在元素树的先序遍历中遇到的顺序。

    QDomElement docElem = doc.documentElement();
    QDomNodeList list = doc.elementsByTagName("a");
    for(int i = 0;i < list.count();++i)
    {
        QDomElement e = list.at(i).toElement();
        qDebug()<<e.attribute("attr");
    }

18、QDomNodeList elementsByTagNameNS(const QString &nsURI, const QString &localName)

返回一个 QDomNodeList,其中包含文档中具有本地名称 localName 和 nsURI 的命名空间 URI 的所有元素。节点列表的顺序是它们在元素树的先序遍历中遇到的顺序。        

19、QDomNode importNode(const QDomNode &importedNode, bool deep)

将节点importedNode 从另一个文档导入到当前文档。此函数创建可在此文档中使用的副本。

该函数返回属于该文档的导入节点。 返回的节点没有父节点。

如果 deep 为真,则该函数不仅导入节点importedNode,还导入其整个子树。如果为false,则仅导入importedNode。参数 deep 对 QDomAttr QDomEntityReference 节点没有影响,因为 QDomAttr 节点的后代总是被导入而 QDomEntityReference 节点的后代永远不会被导入。

根据节点类型,此函数的行为略有不同:

  • QDomAttr:在生成的属性中,owner 元素设置为 0,指定标志设置为 true。始终为属性节点导入importNode 的整个子树:deep 无效。
  • QDomDocument:无法导入文档节点。
  • QDomDocumentFragment:如果 deep 为真,则该函数导入整个文档片段,否则它只会生成一个空的文档片段。
  • QDomDocumentType:文档类型节点无法导入。
  • QDomElement:仅导入 QDomAttr::specified() 为 true 的属性,不导入其他属性。如果 deep 为真,则该函数还导入了importedNode 的子树;否则它只导入元素节点。
  • QDomEntity:实体节点可以导入,但无法使用。
  • QDomEntityReference:实体引用节点的后代不会被导入,deep 没有效果。
  • QDomNotation:Notation 节点可以被导入,但目前没有办法使用它们。
  • QDomProcessingInstruction:将处理指令的目标和值复制到新节点。
  • QDomText:将文本复制到新节点。
  • QDomCDATASection:将文本复制到新节点。
  • QDomComment:将文本复制到新节点。

20、bool setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg = nullptr, int *errorLine = nullptr, int *errorColumn = nullptr)

        bool setContent(QIODevice *dev, bool namespaceProcessing, QString *errorMsg = nullptr, int *errorLine = nullptr, int *errorColumn = nullptr)

从字节数组/设备数据中解析 XML 文档并将其设置为文档的内容。它尝试按照 XML 规范的要求检测文档的编码。

如果namespaceProcessing 为true,解析器会识别XML 文件中的名称空间并将前缀名称、本地名称和名称空间URI 设置为适当的值。如果 namespaceProcessing 为 false,则解析器在读取 XML 文件时不进行命名空间处理。

如果发生解析错误,该函数返回false,错误信息放在*errorMsg 中,*errorLine 中的行号和*errorColumn 中的列号(除非关联的指针设置为0);否则此函数返回真。 QXmlParseException 类文档中描述了各种错误消息。请注意,如果您想向应用程序的用户显示这些错误消息,除非明确翻译,否则它们将以英文显示。

如果namespaceProcessing 为true,则函数QDomNode::prefix() 返回所有元素和属性的字符串。如果元素或属性没有前缀,则返回空字符串。

仅由空格组成的文本节点将被剥离并且不会出现在 QDomDocument 中。如果不需要这种行为,可以使用允许提供 QXmlReader setContent() 重载。

21、bool setContent(const QString &text, bool namespaceProcessing, QString *errorMsg = nullptr, int *errorLine = nullptr, int *errorColumn = nullptr)

       bool setContent(const QString &text, QString *errorMsg = nullptr, int *errorLine = nullptr, int *errorColumn = nullptr)

重载函数。由于文本已经是 Unicode 字符串,因此没有进行编码检测。

22、bool setContent(QXmlStreamReader *reader, bool namespaceProcessing, QString *errorMsg = nullptr, int *errorLine = nullptr, int *errorColumn = nullptr)

重载函数。该函数从 QXmlStreamReader 读取 XML 文档并对其进行解析。

23、QByteArray toByteArray(int indent = 1)

将解析后的文档转换回其文本表示,并返回包含编码为 UTF-8 的数据的 QByteArray。

使用 indent 作为缩进子元素的缩进量。

24、QString toString(int indent = 1)

将解析后的文档转换回其文本表示。使用 indent 作为缩进子元素的缩进量。如果缩进为 -1,则不添加空格。

  • 11
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要将XML文件读取到QDomDocument对象中,可以使用QXmlStreamReader类和QDomDocument类。以下是一个简单的例子: ```cpp #include <QFile> #include <QXmlStreamReader> #include <QDomDocument> QFile file("example.xml"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; QXmlStreamReader xmlReader(&file); QDomDocument domDocument; while (!xmlReader.atEnd()) { xmlReader.readNext(); if (xmlReader.isStartElement()) { QDomElement element = domDocument.createElement(xmlReader.name().toString()); domDocument.appendChild(element); if (xmlReader.attributes().count() > 0) { for (int i = 0; i < xmlReader.attributes().count(); i++) { QDomAttr attr = domDocument.createAttribute(xmlReader.attributes().at(i).name().toString()); attr.setValue(xmlReader.attributes().at(i).value().toString()); element.setAttributeNode(attr); } } } else if (xmlReader.isCharacters()) { QDomText text = domDocument.createTextNode(xmlReader.text().toString()); domDocument.lastChild().appendChild(text); } else if (xmlReader.isEndElement()) { domDocument.removeChild(domDocument.lastChild()); } } if (xmlReader.hasError()) return; file.close(); ``` 在这个例子中,我们打开一个XML文件,并且创建一个QXmlStreamReader对象来读取该文件。然后,我们创建一个QDomDocument对象来存储XML文件的内容。我们使用while循环来遍历XML文件中的所有元素,属性和文本节点。在循环中,我们检查当前节点的类型,并根据需要创建QDomElement,QDomAttr和QDomText对象,并将它们添加到QDomDocument对象中。最后,我们检查是否有任何错误,并关闭文件。 注意:这个例子只是一个简单的例子,如果XML文件非常大或者非常复杂,可能需要使用更复杂的算法来读取和解析XML文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值