相关文章推荐
纯真的领结  ·  npm ...·  1 周前    · 
年轻有为的双杠  ·  npm ERR! gyp ERR! ...·  1 周前    · 
火星上的海豚  ·  js ...·  1 周前    · 
耍酷的大象  ·  jsplumb 5.x 实践分享 ...·  1 年前    · 
强悍的苹果  ·  sequential quadratic ...·  1 年前    · 
热心的皮蛋  ·  HTB_Three之aws ...·  1 年前    · 
QtXml:QDomDocument、QDomNode

QtXml:QDomDocument、QDomNode

8 个月前

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());


免费学习C++ Qt开发教程视频,点击下面链接免费报名领取视频学习资料

ke.qq.com/course/444655?

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,则不添加空格。


QDomNode

一、描述

QDomNode是文档树的节点。

QDomNode 类的副本使用显式共享来共享它们的数据。这意味着修改一个节点将更改所有副本。

下面的示例查找 XML 文档中的第一个元素并打印作为其直接子元素的所有元素的名称。

QDomDocument d;
d.setContent(someXML);
QDomNode n = d.firstChild();
while (!n.isNull())
if (n.isElement())
QDomElement e = n.toElement();
cout << "Element name: " << e.tagName() << Qt::endl;
break;
n = n.nextSibling();
}

二、类型成员

1、enum QDomNode::EncodingPolicy:此枚举指定 save() 如何确定序列化时使用的编码。

  • EncodingFromDocument:编码是从文档中获取的。
  • EncodingFromTextStream:编码是从 QTextStream 中获取的。

2、enum QDomNode::NodeType:节点类型。

ElementNode
AttributeNode
TextNode
CDATASectionNode
EntityReferenceNode
EntityNode
ProcessingInstructionNode
CommentNode
DocumentNode
DocumentTypeNode
DocumentFragmentNode
NotationNode
BaseNode