QT框架下的文本操作(四)

本文详细介绍了XML文件的格式、特点及其实现软件运行参数配置的方法。深入探讨了使用QtXml模块进行XML文件的加载、解析、修改和释放的具体过程,并提供了创建、修改和读取XML元素的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

XML文件

xml为可扩展标记语言,是互联网数据传输的重要工具,它可以跨越互联网任何的平台,不受编程语言和操作系统的限制。同时,为了实现软件运行参数的可配置化,xml文件也是及其有效的手段。

XML文件格式

xml声明
<?xml version='1.0' encoding='gb2312'?>

xml声明一般是xml文档的第一行,xml声明由 versionencoding 组成,version 为文档规范版本,encoding 为文档字符编码,默认编码为 UTF-8

xml元素
<test>789</test>

test为元素的标签,开始和结束的标签必须一一对应。

xml属性
<parameter type="runinfo" id="1">
</parameter>

属性值用双引号包裹;一个元素可以有多个属性,它的基本格式为:
<元素名 属性名=“属性值” 属性名=“属性值”>

xml实体

在xml中,一些字符有特殊的含义,例如 <,如果我们把 < 放到元素中,整个xml的格式就会出错:

<test>1 < 2</test>

为了避免出错,可以用实体引用来代替 <

<test>1 &lt; 2</test>

xml中5个预定义实体:

实体符号
&lt;<
&gt;>
&amp;&
&quot;"
&apos;'

XML示例

<?xml version='1.0' encoding='gb2312'?>
<scene name="parameter">
    <parameter type="person">
        <name>Tim</name>
        <age>26</age>
    </parameter>
</scene>

XML解析

使用 QtXml 模块对xml进行解析。

    QFile *m_localfile;
    QDomDocument *m_dom;
	QTextStream *m_floStream;
	QString m_fileName;			// xml文件名
加载xml文件:
void XmlUtil::loadXml()
{
	if (m_fileName != "")
	{
		m_localfile = new QFile(m_fileName);
		if (!m_localfile->open(QFile::ReadWrite | QFile::Text)) {
			qDebug() << "fail to open config1";
			return;
		}

		m_floStream = new QTextStream(localfile);
		QTextCodec *codec = QTextCodec::codecForName("GB2312");
		m_floStream->setCodec(codec);
		QString xmlDataStr = m_floStream->readAll();

		m_dom = new QDomDocument();
		if (!m_dom->setContent(xmlDataStr)) {
			qDebug() << "fail to open config2";
			m_localfile->close();
			return;
		}
	}
}
释放xml文件:
void XmlUtil::freeXml()
{
	if (localfile)
	{
		localfile->close();
		delete localfile;
		localfile = NULL;
	}

	if (dom)
	{
		delete dom;
		dom = NULL;
	}
	
	if (floStream)
	{
		delete floStream;
		floStream = NULL;
	}
}
创建元素
// @param tagName:tag名,如 示例中的 parameter
// @param attriName:属性名,如 示例中的 type
// @param attriValue:属性值,如 示例中的 person
// @param keyNodeInfos:元素信息,如 {"name",["Tim"]},{"age",["26"]}
QDomNode XmlUtil::createNode(const QString &tagName, const QString &attriName, const QString &attriValue,
	const QMap<QString, QStringList> &keyNodeInfos)
{
	QDomElement mainElement = dom->createElement(tagName);

	if (!attriName.isEmpty())
	{
		QDomAttr mainDomAttr = dom->createAttribute(attriName);
		mainDomAttr.setValue(attriValue);
		mainElement.setAttributeNode(mainDomAttr);
	}

	for (auto it = keyNodeInfos.constBegin(); it != keyNodeInfos.constEnd(); it++)
	{
		for (auto subIt = it.value().constBegin(); subIt != it.value().constEnd(); subIt++)
		{
			QDomElement subElement = dom->createElement(it.key());
			QDomText nodeText = dom->createTextNode(*subIt);
			subElement.appendChild(nodeText);
			mainElement.appendChild(subElement);
		}
	}

	return mainElement;
}
修改xml文件
/**
    * 修改xml配置文件
    * @param name: "scene"元素的"name"属性值
    * @param type: "parameter"元素的"type"属性值
    * @param key: 元素名,如"age"
    * @param value:元素值,如果有多个,则创建多个元素
    */
bool XmlUtil::writeValue(const QString &name,const QString &type,const QString &key,const QStringList& value)
{
	if (dom == NULL)
		return false;

	bool isExist = false;
	QDomNodeList mainNodes = dom->childNodes();

    // 先找到 "scene"元素的"name"属性值为 name 的子元素A
	for (int mainNodeNum = 0; mainNodeNum < mainNodes.size(); mainNodeNum++)
	{
		QDomNode mainNode = mainNodes.at(mainNodeNum);
		if (mainNode.toElement().attributeNode("name").value() == name)
		{
			QDomNode oldMainNode = mainNode;

            // 再从子元素A中找到 "parameter"元素的"type"属性值为 type 的子元素B
			QDomNodeList subNodes = mainNode.childNodes();
			for (int subNodeNum = 0; subNodeNum < subNodes.size(); subNodeNum++)
			{
				QDomNode node = subNodes.at(subNodeNum);
				if (node.toElement().attributeNode("type").value() == type)
				{
					QDomNode cloneNode = node;

                    // 再从子元素B中找到 元素名为key的元素
					isExist = true;
					QDomNodeList childNodes = node.childNodes();
					int num = 0;
					for (int childNodeNum = 0; childNodeNum < childNodes.count(); childNodeNum++)
					{
						QDomNode mynode = childNodes.at(childNodeNum);
						if (mynode.nodeName() == key)
						{
							QDomNode myOldNode = mynode;
							if (num < value.size())
							{
                                // 设置元素值
								if (mynode.hasChildNodes())
								{
									QDomNode oldNode = mynode.firstChild();
									mynode.firstChild().setNodeValue(value.at(num));
									QDomNode newNode = mynode.firstChild();
									mynode.replaceChild(newNode, oldNode);
								}
								else
								{
									QDomText nodeText = dom->createTextNode(value.at(num));
									mynode.appendChild(nodeText);
								}
							}
							num++;

							node.replaceChild(mynode, myOldNode);
						}
					}

                    // 如果现有元素个数num 小于 value的长度size,那么创建 size-num 个元素
					for (; num < value.size(); num++)
					{
						QDomElement element = dom->createElement(key);
						node.appendChild(element);
						QDomText nodeText = dom->createTextNode(value.at(num));
						element.appendChild(nodeText);
					}

					mainNode.replaceChild(node, cloneNode);
				}
			}

            // 如果没有找到 "parameter"元素的"type"属性值为 type 的子元素B,那么创建它
			if (!isExist)
			{
				QMap<QString, QStringList> keyNodeInfos;
				keyNodeInfos.insert(key, value);
				QDomNode subElement = createNode("parameter", "type", type, keyNodeInfos);

				mainNode.appendChild(subElement);
				isExist = true;
			}

			dom->replaceChild(mainNode,oldMainNode);
		}
	}

    // 如果没有找到 "scene"元素的"name"属性值为 name 的子元素A,那么创建它
	if (!isExist)
	{
		QMap<QString, QStringList> keyNodeInfos;
		keyNodeInfos.insert(key, value);
		QDomNode mainNode = createNode("scene", "name", name);
		QDomNode subNode = createNode("parameter", "type", type, keyNodeInfos);
		mainNode.appendChild(subNode);

		dom->appendChild(mainNode);
		isExist = true;
	}

	localfile->resize(0);
	dom->save(*floStream,4);
	return true;
}
读取xml文件
/**
 * 获取配置文件中的值
 * @param name: "scene"元素的"name"属性值
 * @param type: "parameter"元素的"type"属性值
 * @param key: 元素名,如"age"
 * @return 元素值,如果找到多个满足要求的元素,那么返回链表
 */
QStringList XmlUtil::getValue(const QString &name,const QString &type,const QString &key)
{
	QStringList result;

	if (dom == NULL)
		return result;

	QDomNodeList nodelist = dom->elementsByTagName(name);
	for(int i=0; i<nodelist.count(); i++)
	{
		QDomNode node = nodelist.at(i);
		if (node.toElement().attributeNode("type").value() == type)
		{
			QDomNodeList itemlist = node.childNodes();
			for(int j=0; j<itemlist.count(); j++)
			{
				QDomNode mynode = itemlist.at(j);
				if (mynode.nodeName() == key)
					result << mynode.firstChild().nodeValue();
			}
		}
	}
	if (result.isEmpty())
		qDebug() << QString("there is no key as %1").arg(key);
	return result;
}

这样的话,我们就可以很方便的读取、修改xml文件。例如:

  • 读取示例xml中的age
int ageValue = getValue("parameter", "person", "age").first().toInt();
  • 修改示例xml中的name
bool isSuccess = writeValue("parameter", "person", "name", QStringList() << "Peter");

完整的文本操作源码,点击此处下载。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值