How to manipulate XML and notice problems with tinyxml

  • 2020-04-01 21:28:22
  • OfStack

In the last blog post, we looked at the architecture of the tinyxml tool, and in this blog post, we'll go into more detail on how to manipulate XML using tinyxml. And in the process of operation, we should pay attention to the problem.
Start by importing the tinyxml source into your own project, with the following effect:
        < img Alt = "" border = 0 SRC =" / / files.jb51.net/file_images/article/201301/2013010312002935.png ">
    Actually, add the file directly to the project:   < img Alt = "" border = 0 height = 379 SRC =" / / files.jb51.net/file_images/article/201301/2013010312002936.gif "width = 316 >
If your system is Windows 7 or office is more than 2007, add file this function is not used, the result is: or directly crash. Or nothing. The solution is as follows:
(link: #)
The environment is ready, so let's get started. Just like the operation on the database table -- add, delete, change, check. According to this logic, start by adding (creating).
The format is as follows:
 
<Persons> 
<Person> 
<name>lhy</name> 
<age>22</age> 
</Person> 
</Persons> 

In the last blog post, we also covered all the classes in the tinyxml parser and the relationships between them.
Create the XML in the above format, the code is as follows:
 
//Create an XML document object.
TiXmlDocument *myDocument = new TiXmlDocument(); 
//Create a root element and connect.
TiXmlElement *RootElement = new TiXmlElement("Persons"); 
myDocument->LinkEndChild(RootElement); 
//Create a Person element and connect.
TiXmlElement *PersonElement = new TiXmlElement("Person"); 
RootElement->LinkEndChild(PersonElement); 
//Create the name element, the age element, and the connection.
TiXmlElement *NameElement = new TiXmlElement("name"); 
TiXmlElement *AgeElement = new TiXmlElement("age"); 
PersonElement->LinkEndChild(NameElement); 
PersonElement->LinkEndChild(AgeElement); 
//Sets and connects the contents of the name and age elements.
TiXmlText *NameContent = new TiXmlText("lhy"); 
TiXmlText *AgeContent = new TiXmlText("22"); 
NameElement->LinkEndChild(NameContent); 
AgeElement->LinkEndChild(AgeContent); 
myDocument->SaveFile("d:\lhy\xml.txt");//Save to file

As long as you understand the relationships between nodes in XML, creation is not a problem. It's simply a generational relationship.
Created, but as a C++ program ape, after writing, always feel a little awkward, always feel what is wrong. Do you see the catch?
By the way, there are a lot of New Pointers in a little bit of code. There is no garbage collection mechanism in Java in C++. You have to deal with the garbage yourself. But there is no Delete statement in the code?
Search the Internet, found a lot of create code, there is no Delete statement? Does everybody copy and paste? Or is tinyxml acting up?
I summarized the following points, but in the end the development process is still a question, but the development process, there is no problem, so my program for the time being.
Statement 1: in many articles, there is no delete in new because tinyxml can be automatically released and the pointer is automatically destroyed without the developer having to manually release it.
Question: new out can automatically release? New is created on the heap. When will it be automatically released? At the end of the program, automatically release? So how do you tell when the program is over? We'll talk more about how to destruct memory regions in one module in another later.
Since tinyxml has a self-destruct function, we looked up its source code and found that, indeed, there is a corresponding pointer release in the destructor in tinyxml. But not for every node.
Details in the source code:
 
TiXmlNode::~TiXmlNode() 
{ 
TiXmlNode* node = firstChild; 
TiXmlNode* temp = 0; 
while ( node ) 
{ 
temp = node; 
node = node->next; 
delete temp; 
} 
} 
void TiXmlNode::Clear() 
{ 
TiXmlNode* node = firstChild; 
TiXmlNode* temp = 0; 
while ( node ) 
{ 
temp = node; 
node = node->next; 
delete temp; 
} 
firstChild = 0; 
lastChild = 0; 
} 

We also know that there are inheritance relationships between classes in tinyxml.
So let's look at the TixmlElement class in tinyxml:
 
TiXmlElement::~TiXmlElement() 
{ 
ClearThis(); 
} 
void TiXmlElement::ClearThis() 
{ 
Clear(); 
while( attributeSet.First() ) 
{ 
TiXmlAttribute* node = attributeSet.First(); 
attributeSet.Remove( node ); 
delete node; 
} 
} 

Because TixmlElement inherits TiXmlNode. But there is no TiXmlDocument class destructor found in TiXmlDocument.
The second way: TiXmlDocument object is the root of the tree node, in a complete document, in addition to it, the rest of the nodes must be its descendants, so TinyXml USES a very ingenious method to destructor each node of the object, each node of the destructor tasks entrusted to it by their father, so just make sure father was correct destructor, or call the father of the Clear function, all of its descendants will be correct destructor, so for the entire document just TiXmlDocument object is correctly destructor.
In the code we created above, we found that all the nodes are hanging below the root node.
Actually this code: myDocument-> LinkEndChild (RootElement); Polymorphic mode is used. The relationship between classes is as follows:
< img Alt = "" border = 0 SRC =" / / files.jb51.net/file_images/article/201301/2013010312002937.png ">    
And the LinkEndChild source code is as follows: it is a method in the parent class TiXmlNode
 
TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) 
{ 
assert( node->parent == 0 || node->parent == this ); 
assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); 
if ( node->Type() == TiXmlNode::DOCUMENT ) 
{ 
delete node; 
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); 
return 0; 
} 
node->parent = this; 
node->prev = lastChild; 
node->next = 0; 
if ( lastChild ) 
lastChild->next = node; 
else 
firstChild = node;// it was an empty list. 
lastChild = node; 
return node; 
} 

In this case: as long as the root node is deleted, in the program, myDocument, is equivalent to the removal of TiXmlNode, is equivalent to calling the TiXmlNode destructor.
Doubt: the web says this way, destructions are from leaves to roots. According to the destructor in TiXmlNode, we can conclude that it is from root to leaf.
But when we Delete myDocument, we should pay attention to one thing:
When you create a document, that's myDocument in the program segment. If created from the heap, manual release is required. As in our fragment above, it is created on the heap.
TiXmlDocument * myDocument = new TiXmlDocument ();
If created from the stack, we do not have to release manually, but the program automatically calls the destructor. We should also note that other elements must be created on the heap. Because in the TiXmlNode destructor, it is delete, but nothing on the stack needs to be deleted, the connected descendants other than the root must be created from the heap.
After our explanation, do you understand the principle in tinyxml? As long as you understand the role of classes in tinyxml and the relationship between classes, the source code is no problem oh.
This blog explains the problems with creating a little XML demo. In the next blog post, we'll answer questions about parsing based on parsing XML.

Related articles: