我试图使用TinyXML解析XML文件,以便构建通用树。我尝试递归地做这个。问题是,每当我这样做时,我都会得到分割错误。
下面是代码片段:void buildTree() {
// Loading XML file and getting rootNode
string filename = "generalTree.xml";
TiXmlDocument doc(filename);
bool loadOkay = doc.LoadFile();
if (!loadOkay) {
cout << "Could not load file " << filename << endl;
cout << "Error='" << doc.ErrorDesc() <<"'. Exiting.n";
}
TiXmlNode* generalTreeNode = doc.FirstChild("GeneralTree");
TiXmlNode* rootNode = generalTreeNode->FirstChild();
int key = stoi(rootNode->ToElement()->Attribute("key"));
Type data = rootNode->ToElement()->GetText();
root = new TreeNode<Type>("General", key, data);
// Populating the rest of the tree via recursive function
recFunction(rootNode);
}
下面是recFunction:
void recFunction(TiXmlNode *node) {
if(node->FirstChildElement() == NULL) {
cout << "First child element is null" << endl;
} else {
int key = stoi(node->ToElement()->Attribute("key"));
Type data = node->ToElement()->GetText();
TreeNode<Type> *treeNode = new TreeNode<Type>("General", key, data);
cout << "Right BEFORE recursive activates" << endl;
return recFunction(node->FirstChild());
}
cout << "After recursiveness done" << endl;
// After recursiveness is finished
while(node->NextSibling() != NULL) {
if(!node) {
cout << "Node is null, breaking" << endl;
break;
}
// Converting XML node to TreeNode
cout << "DOING NODE TO ELEMENT" << endl;
cout << node->ToText()->Value() << endl;
cout << "Node is of type: " << typeid(node).name() << endl;
cout << node->ToElement()->Attribute("key") << endl;
cout << "DONE WITH NODE TO ELEMENT" << endl;
int key = stoi(node->ToElement()->Attribute("key"));
cout << "Key 1 is: " << key << endl;
Type data = node->ToElement()->GetText();
cout << "Data 1 is: " << data << endl;
TreeNode<Type> *prev = new TreeNode<Type>("General", key, data);
int key2 = stoi(node->NextSibling()->ToElement()->Attribute("key"));
Type data2 = node->ToElement()->GetText();
TreeNode<Type> *cur = new TreeNode<Type>("General", key2, data2);
// Create linked list of siblings
prev->setSibling(cur);
node = node->NextSibling();
}
cout << "End of while loop reached" << endl;
}
下面是XML文件:
<?xml version="1.0"?>
<GeneralTree>
<Node key="1"> Genres
<Node key="2">Thriller</Node>
<Node key="3">Action</Node>
<Node key="4">Romance
<Node key="7">A Walk To Remember</Node>
<Node key="8">The Notebook</Node>
<Node key="9">Safe Haven</Node>
</Node>
<Node key="5">Anime
<Node key="9">Full Metal Alchemist</Node>
<Node key="10">Pokemon 2000: The Movie</Node>
</Node>
</Node>
<Node key="12">Genre Sister</Node>
</GeneralTree>
现在,我将问题隔离到recFunction中的以下行:
cout << "DOING NODE TO ELEMENT" << endl;
cout << node->ToText()->Value() << endl;
cout << "Node is of type: " << typeid(node).name() << endl;
cout << node->ToElement()->Attribute("key") << endl;
cout << "DONE WITH NODE TO ELEMENT" << endl;
所以我假设节点在递归函数的某个点变为空。问题是我看了一遍又一遍,我似乎不知道为什么。适当的检查应该防止node变为null。
下面是我收到的输出(包括打印语句,以便您可以看到它在哪里发生)。
Right BEFORE recursive activates
First child element is null
After recursiveness done
DOING NODE TO ELEMENT
Genres
Node is of type: P9TiXmlNode
提前感谢!
编辑:下面是当我运行gdb并在 处使用断点时发生的情况 cout << node->ToText()->Value() << endl;
和cout & lt; & lt;节点-> ToElement() ->属性("关键")& lt; & lt;endl;
Right BEFORE recursive activates
First child element is null
After recursiveness done
DOING NODE TO ELEMENT
Breakpoint 1, GeneralTree<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::recFunction (this=0x100300040, node=0x1003005c0)
at ./GeneralTree.h:70
70 cout << node->ToText()->Value() << endl;
(gdb) c
Continuing.
Genres
Node is of type: P9TiXmlNode
Breakpoint 2, GeneralTree<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::recFunction (this=0x100300040, node=0x1003005c0)
at ./GeneralTree.h:72
72 cout << node->ToElement()->Attribute("key") << endl;
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
TiXmlAttributeSet::Find (this=0x60, name=0x100018ede "key") at tinyxml.cpp:1527
1527 for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
有很多事情,但它们都归结为相同的概念错误。
XML节点包括文本、空格和属性,而不仅仅是元素。
如果你想递归遍历所有元素,这是错误的:
return recFunction(node->FirstChild());
应该是这样的:
return recFunction(node->FirstChildElement());
同样,当你要求NextSibling
时,你可能想要NextSiblingElement
。
int key2 = stoi(node->NextSibling()->ToElement()->Attribute("key"));
如果NextSibling
返回一个文本节点,那么ToElement
将返回null。
查看SEGV信息:
TiXmlAttributeSet::Find (this=0x60, name=0x100018ede "key") at tinyxml.cpp:1527
这显示了0x60的this
指针值,它不太可能有效。获得这种指针的最可能的方法是在空指针的类型强制转换中进行未检查的指针调整。也就是说,你在某些时候使用了一个空指针,而你的代码或库代码将它强制转换为相关的类型。
在本例中,既然node->ToText()
成功了,那么node->ToElement()
必然返回null
,因为节点要么是文本节点,要么是元素节点。因此,ToElement
的返回值为null,对其调用Attribute
是错误的。