我对在C++中使用XML非常陌生,我正试图解析要下载的文件列表。我使用的THe XML文件是通过PHP生成的,如下所示:
<?xml version="1.0"?>
<FileList>
<File Name="xxx" Path="xxx" MD5="xxx" SHA1="xxx"/>
</FileList>我在C++中使用的代码如下,我使用了一些在线教程(它包含在一些全局函数中):
tinyxml2::XMLDocument doc;
doc.LoadFile("file_listing.xml");
tinyxml2::XMLNode* pRoot = doc.FirstChild();
tinyxml2::XMLElement* pElement = pRoot->FirstChildElement("FileList");
if (pRoot == nullptr)
{
QString text = QString::fromLocal8Bit("Error text in french");
//other stuff
}
else
{
tinyxml2::XMLElement* pListElement = pElement->FirstChildElement("File");
while (pListElement != nullptr)
{
QString pathAttr = QString::fromStdString(pListElement->Attribute("Path"));
QString md5Attr = QString:: fromStdString(pListElement->Attribute("MD5"));
QString sha1Attr = QString::fromStdString(pListElement->Attribute("SHA1"));
QString currentPath = pathAttr.remove("path");
QString currentMd5 = this->fileChecksum(currentPath, QCryptographicHash::Md5);
QString currentSha1 = this->fileChecksum(currentPath, QCryptographicHash::Sha1);
QFile currentFile(currentPath);
if (md5Attr != currentMd5 || sha1Attr != currentSha1 || !currentFile.exists())
{
QString url = "url" + currentPath;
this->downloadFile(url);
}
pListElement = pListElement->NextSiblingElement("File");
}问题是,在下面的行中,我得到了一个类似于“访问冲突,这是nullptr”的错误:
tinyxml2::XMLElement* pListElement = pElement->FirstChildElement("File");
由于我在编码方面不是一个专业人士,而且我已经上下搜索过互联网,我希望这里的人能给我一些指点。
祝大家今天愉快。
发布于 2020-06-02 23:48:12
我不知道您是否有可用的C++17,但是您可以使用auto*和if-init-expressions消除很多干扰(或者依赖于指针可以隐式转换为布尔值这一事实)。
代码的主要问题是,您没有使用XMLElement*,而是使用了XMLNode。函数tinyxml2::XMLDocument::RootElement()会自动为您获取最高级的元素。
因为在顶部有一个xml声明,所以FirstChild返回that...which没有任何子元素,所以其余的代码都失败了。
通过使用RootElement,tinyxml知道跳过任何领先的非元素节点(注释、doctype等)。然后给你<FileList>代替。
tinyxml2::XMLDocument doc;
auto err = doc.LoadFile("file_listing.xml");
if(err != tinyxml2::XML_SUCCESS) {
//Could not load file. Handle appropriately.
} else {
if(auto* pRoot = doc.RootElement(); pRoot == nullptr) {
QString text = QString::fromLocal8Bit("Error text in french");
//other stuff
} else {
for(auto* pListElement = pRoot->FirstChildElement("File");
pListElement != nullptr;
pListElement = pListElement->NextSiblingElement("File"))
{
QString pathAttr = QString::fromStdString(pListElement->Attribute("Path"));
QString md5Attr = QString:: fromStdString(pListElement->Attribute("MD5"));
QString sha1Attr = QString::fromStdString(pListElement->Attribute("SHA1"));
QString currentPath = pathAttr.remove("path");
QString currentMd5 = this->fileChecksum(currentPath, QCryptographicHash::Md5);
QString currentSha1 = this->fileChecksum(currentPath, QCryptographicHash::Sha1);
QFile currentFile(currentPath);
if(md5Attr != currentMd5 || sha1Attr != currentSha1 || !currentFile.exists()) {
QString url = "url" + currentPath;
this->downloadFile(url);
}
}
}
}发布于 2020-06-02 23:02:33
根据tinyxml2 2::XMLNode的参考FirstChild():
获取第一个子节点,如果不存在则为null。
因此,这一行将获得根节点:
tinyxml2::XMLNode* pRoot = doc.FirstChild();这意味着当您试图在根节点中找到一个FileList节点时,它返回null。
要避免访问冲突,请在使用指针之前检查它们是否有效。对于pRoot有一个if检查,但在它试图调用pRoot上的函数之前的行。没有是否检查pElement,所以这就是为什么会出现访问冲突。除了检查指针是有效的,还可以考虑添加带有日志记录的其他块,以说明出了什么问题(例如,“未能找到元素X")。从长远来看,这将对您有所帮助-- XML解析是一项痛苦的工作,即使使用像Tinyxml这样的库,也总是会出现这样的初始问题,因此养成checki指针的习惯并注销有用的消息肯定会有回报。
https://stackoverflow.com/questions/62159742
复制相似问题