Qt解析XML

50 篇文章 0 订阅

背景

本来想解析VS的项目配置文件(*.vcxproj),配合cppclean来发现多余的#incldue

结果发现低估了难度,VS会间接引入许多目录。

略有不甘,暂且作为一个解析XML文件的示例。

代码

VSProjectParser.h

#include <QVector>
#include <memory>

class VSProjectParser {
public:
	VSProjectParser (const QString &vsProjectFilePath);

	QVector<QString> getIncludeDirectoriesRealPath ();

	QVector<QString> getCppFilesRealPath ();

	QVector<QString> getHeadFilesRealPath ();

private:
	class Impl;
	std::shared_ptr<Impl> m_impl = nullptr;
};

VSProjectParser.cpp

#include "VSProjectParser.h"

#include <QDebug>
#include <QDir>
#include <QDomDocument>
#include <QDomElement>
#include <QDomNode>
#include <QFile>
#include <QFileInfo>
#include <QHash>
#include <memory>

class Document {
public:

	Document (const QString &projFilePath);

	QVector<QString> extractCppFiles ();

	QVector<QString> extractHeadFiles ();

private:

	void extractTasgInfo ();

	QHash<QString, QVector<QString>> m_tagsInfo = {};
	QString m_projFilePath						= "";
};

class VSProjectParser::Impl {
public:
	Impl (const QString &vsProjectFilePath) : m_vsProjectFileInfo (vsProjectFilePath), m_document (vsProjectFilePath)
	{
	}

	QFileInfo m_vsProjectFileInfo = "";
	Document m_document;
};

Document::Document (const QString &projFilePath) : m_projFilePath (projFilePath)
{
	extractTasgInfo();
}

QVector<QString>
Document::extractCppFiles()
{
	QVector<QString> cppTags {"ClCompile"};
	QVector<QString> ret;
	for (QString tag : cppTags) {
		if (m_tagsInfo.contains (tag))
			ret.append (m_tagsInfo.value (tag));
	}
	return ret;
}

QVector<QString>
Document::extractHeadFiles()
{
	QVector<QString> headTags {"ClInclude", "QtMoc"};

	QVector<QString> ret;
	for (QString tag : headTags) {
		if (m_tagsInfo.contains (tag))
			ret.append (m_tagsInfo.value (tag));
	}
	return ret;
}

void
Document::extractTasgInfo()
{
	QFile file (m_projFilePath);
	if (!file.open (QIODevice::ReadOnly)) {
		qDebug() << "Failed to open the file.";
		return;
	}

	QDomDocument doc;
	if (!doc.setContent (&file)) {
		qDebug() << "Failed to parse the file into a DOM tree.";
		return;
	}
	file.close();

	QDomElement root = doc.documentElement();

	QHash<QString, QVector<QString>> tags_with_include_attribute;

	constexpr auto ATTR_INCLUDE = "Include";

	QDomNodeList itemGroups = root.elementsByTagName ("ItemGroup");
	for (int i = 0; i < itemGroups.count(); ++i) {
		QDomNode itemGroup	  = itemGroups.at (i);
		QDomNodeList children = itemGroup.childNodes();

		for (int j = 0; j < children.count(); ++j) {
			QDomNode child = children.at (j);
			if (child.isElement()) {
				QDomElement element = child.toElement();
				QString tagName		= element.tagName();
				tags_with_include_attribute[tagName].push_back (element.attribute (ATTR_INCLUDE));
			}
		}
	}
	QVector<QString> keys;
	m_tagsInfo = tags_with_include_attribute;
}

VSProjectParser::VSProjectParser (const QString &vsProjectFilePath) : m_impl (new Impl (vsProjectFilePath))
{
}

QVector<QString>
VSProjectParser::getIncludeDirectoriesRealPath()
{
	QVector<QString> headers = getHeadFilesRealPath();

	QVector<QString> ret;
	for (QString &file : headers) {
		QFileInfo fileInfo (file);
		if (!fileInfo.exists()) {
			qDebug() << __FUNCTION__ << "File not found:" << file;
			continue;
		}
		ret.append (fileInfo.dir().absolutePath());
	}
	return ret;
}

QVector<QString>
VSProjectParser::getCppFilesRealPath()
{
	QVector<QString> includes = m_impl->m_document.extractCppFiles();

	QVector<QString> ret;
	for (QString &file : includes) {
		file = m_impl->m_vsProjectFileInfo.dir().absolutePath() + "/" + file;

		QFileInfo fileInfo (file);
		if (fileInfo.exists())
			ret.append (fileInfo.absoluteFilePath());
		else
			qDebug() << __FUNCTION__ << "File not found:" << file;
	}
	return ret;
}

QVector<QString>
VSProjectParser::getHeadFilesRealPath()
{
	QVector<QString> includes = m_impl->m_document.extractHeadFiles();

	QVector<QString> ret;
	for (QString &file : includes) {
		file = m_impl->m_vsProjectFileInfo.dir().absolutePath() + "/" + file;

		QFileInfo fileInfo (file);
		if (fileInfo.exists())
			ret.append (fileInfo.absoluteFilePath());
		else
			qDebug() << __FUNCTION__ << "File not found:" << file;
	}
	return ret;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

barbyQAQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值