GEAR  1.9.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Friends Pages
MergeXML.cc
1 #include "gear/GEAR.h"
2 #include "gearxml/MergeXML.h"
3 
4 #include <sstream>
5 
6 namespace gear{
7 
8 
9  bool MergeXML::setFile1( const std::string& fileName ) {
10 
11  _file1 = new TiXmlDocument( fileName ) ;
12 
13  return _file1->LoadFile( fileName ) ;
14  }
15 
16 
17  bool MergeXML::setFile2( const std::string& fileName ) {
18 
19  _file2 = new TiXmlDocument( fileName ) ;
20 
21  return _file2->LoadFile( fileName ) ;
22  }
23 
24 
25  void MergeXML::correctDominantFile() {
26 
27  if ( _domFile == 1 ) {
28  _fileSwap = new TiXmlDocument ;
29  *_fileSwap = *_file1 ;
30  *_file1 = *_file2 ;
31  *_file2 = *_fileSwap ;
32  }
33  }
34 
35 
36  bool MergeXML::mergeFiles (const std::string& fileName) {
37 
38  // debug information
39  //std::cout << "mergeFiles called for "<< fileName << std::endl ;
40 
41  // variables
42  const std::string gear = "gear" ;
43  const std::string global = "global" ;
44  const std::string detectors = "detectors" ;
45  const std::string materials = "materials" ;
46 
47  // correct the files for dominancy
48  correctDominantFile() ;
49 
50  // copy all dominant information in final file
51  _fileMerged = new TiXmlDocument( fileName ) ;
52  *_fileMerged = *_file2 ;
53 
54  // check if files are geartype
55  if ( not ( _file1->FirstChild( gear ) && _fileMerged->FirstChild( gear )
56  && (_file1->FirstChild( gear ))->FirstChild( detectors )
57  && (_fileMerged->FirstChild( gear ))->FirstChild( detectors )
58  )) {
59 
60  // give out information and quit
61  std::cout << "Files are not of type gear.\nAborted." <<std::endl ;
62  return false;
63  }
64 
65  // go to specified nodes
66  TiXmlNode* nodeGear1 = _file1->FirstChild( gear ) ;
67  TiXmlNode* nodeGlobal1 = nodeGear1->FirstChild( global ) ;
68  TiXmlNode* nodeDetectors1 = nodeGear1->FirstChild( detectors ) ;
69  TiXmlNode* nodeMaterials1 = nodeGear1->FirstChild( materials ) ;
70 
71  TiXmlNode* nodeGearMerged = _fileMerged->FirstChild( gear ) ;
72  TiXmlNode* nodeGlobalMerged = nodeGearMerged->FirstChild( global ) ;
73  TiXmlNode* nodeDetectorsMerged = nodeGearMerged->FirstChild( detectors ) ;
74  TiXmlNode* nodeMaterialsMerged = nodeGearMerged->FirstChild( materials ) ;
75 
76  // loop through all nodes
77  mergeNode( nodeGlobal1, nodeGlobalMerged ) ;
78  mergeNode( nodeDetectors1, nodeDetectorsMerged ) ;
79  mergeNode( nodeMaterials1, nodeMaterialsMerged ) ;
80 
81  // save file
82  return _fileMerged->SaveFile( fileName ) ;
83  }
84 
85 
86  // compare nodes
87  void MergeXML::mergeNode( TiXmlNode* node, TiXmlNode* domNode ) {
88 
89  // during the loop count occurences of same Name
90  int occurence = 0 ;
91  std::string lastName ;
92 
93 
94  // debug information
95 // if ( node->ToComment() ) std::cout << "node is Comment." << std::endl;
96 // if ( node->ToText() ) std::cout << "node is Text." << std::endl;
97 // if ( node->ToElement() ) std::cout << "node is Element." << std::endl;
98 // if ( node->ToUnknown() ) std::cout << "node is Unknown." << std::endl;
99 
100  // skip if node is comment or pure text
101  if (!( !( node->ToText() ) || !( node->ToComment() ) || !( node->ToUnknown() )) ) {
102  // debug information
103  //std::cout << "skipping node "<< getNodeName(node) <<" b/c it is text or comment" << std::endl ;
104  return ;
105  }
106 
107  // loop through all child nodes
108  TiXmlNode* loopNode = 0 ;
109  while (( loopNode = ( node->IterateChildren( loopNode ) )))
110  {
111  // debug information
112  //std::cout << " loopNode " << loopNode -> Value() << std::endl ;
113 
114  // check how often nodes appear
115  int countRec = countNodes( loopNode, node ) ;
116  int countDom = countNodes( loopNode, domNode ) ;
117 
118  // debug information
119  //std::cout << " counter in rec: " << countRec << " counter in dom: " << countDom << std::endl ;
120 
121  // if multiple occurences and number does not match throw
122  if ( ((countRec > 1) || (countDom >1)) && ( countDom != countRec ) ) {
123 
124  // throw
125  std::stringstream s ;
126  s << "ERROR. Counter for " << loopNode->Value() << " returns " << countRec
127  << " while counter for domNode " << domNode->Value() << " returns "
128  << countDom << "." << std::endl ;
129 
130  throw Exception( s.str() ) ;
131 
132  return ;
133  }
134 
135 
136  // count occurences of same name
137  if ( lastName == getNodeName( loopNode ) ) {
138  occurence ++ ;
139  }
140  else {
141  occurence = 1 ;
142  }
143  lastName = getNodeName( loopNode ) ;
144 
145  // get the appropriate child note from dominant node
146  TiXmlNode* domChildNode = getChildNode( loopNode, domNode, occurence ) ;
147 
148  if (domChildNode == NULL ) {
149 
150  // add to domNode
151  domNode->InsertEndChild( *loopNode ) ;
152 
153  // debug information
154  //std::cout << " Added node " << lastName << std::endl ;
155  }
156  else {
157  // check if nodes are elements
158  if (loopNode->ToElement() && domChildNode->ToElement() ) {
159 
160  // merge the attributes of these elements
161  mergeAttribute( (loopNode->ToElement()), (domChildNode->ToElement()) ) ;
162  }
163 
164  // start mergeNode for subordniate nodes
165  if ( hasAttribute(loopNode) && !((loopNode->FirstChild())->ToText()) ) {
166  mergeNode( loopNode, domChildNode ) ;
167  }
168  //else {
169  // std::cout << "skipping to check childnodes because hasAttribtue: "
170  // << hasAttribute(loopNode) << " ToText: "
171  // << !((loopNode->FirstChild())->ToText())
172  // << "." << " true = " << true << std::endl ;
173  // }
174 
175  }
176  } // close Loop
177  }
178 
179 
180  // returns name for Node
181  std::string MergeXML::getNodeName( TiXmlNode* node ) {
182 
183  // if name has to be taken than get name - otherwise take value of node
184  std::string strName ;
185 
186  if ( hasAttribute(node) ) {
187  strName = (node->ToElement())->Attribute( _name ) ;
188  }
189  else {
190  strName = node->Value() ;
191  }
192 
193  return strName ;
194  }
195 
196 
197  // check if node has attribute name
198  bool MergeXML::hasAttribute( TiXmlNode* node ) {
199 
200  return ( (node->ToElement()) && ((node->ToElement())->Attribute(_name)) ) ;
201  }
202 
203 
204  // counts how often nodes appear
205  int MergeXML::countNodes( TiXmlNode* childNode, TiXmlNode* parentNode ) {
206 
207  // counter for appearances
208  int counter = 0 ;
209 
210  // get Name from Node either as value or as attribute name
211  std::string strName = getNodeName( childNode ) ;
212 
213  // loop through all nodes and count
214  TiXmlNode* loopNode = parentNode->FirstChild() ;
215  while ( loopNode ) {
216 
217  // debug information
218  // int i = 0 ; i++ ;
219  // std::cout << "Iterating " << i << std::endl ;
220 
221  std::string loopName = getNodeName( loopNode ) ;
222 
223  // if we have to look for name
224  if ( ( loopName == strName ) && ( hasAttribute(childNode) == hasAttribute(loopNode) ) ) {
225  // count up
226  counter ++ ;
227  }
228 
229  loopNode = loopNode->NextSibling() ;
230 
231  } // close loop
232  return counter ;
233  }
234 
235 
236  // get ChildElement
237  TiXmlNode* MergeXML::getChildNode( TiXmlNode* node, TiXmlNode* domNode, int getOccurence ) {
238 
239  // debug information
240  //std::cout << " getChildElement called for " << node->Value() << std::endl ;
241 
242  // get attribute name
243  std::string searchName = getNodeName( node ) ;
244 
245  // debug information
246  //std::cout << " searching " << searchName << std::endl ;
247 
248  // get first child element
249  // debug information
250  //std::cout << " Starting to loopElements " << node->Value() << std::endl ;
251 
252  TiXmlNode* loopNode = domNode->FirstChild() ;
253 
254  // the occurences of the same element are numbered
255  int occurence = 0 ;
256 
257  while (loopNode )
258  {
259 
260  std::string loopName = getNodeName( loopNode ) ;
261  // debug information
262  //std::cout << " search " << searchName << " in " << loopName << std::endl ;
263 
264  // if found return
265  // if names and attributes match
266  if( (loopName == searchName) && ( hasAttribute(node) == hasAttribute(loopNode) ) ) {
267  occurence ++ ;
268  // debug information
269  //std::cout << " found "<< occurence << " of " << getOccurence << std::endl ;
270  if ( occurence == getOccurence ) {
271  // debug information
272  //std::cout << " returning in occurence " << occurence << std::endl ;
273  return loopNode ;
274  }
275  }
276 
277  // continue loop
278  loopNode = loopNode->NextSibling() ;
279 
280  } // close loop
281  // debug information
282  //std::cout << " returning NULL" << std::endl ;
283  return NULL ;
284  }
285 
286 
287  // compare Attributes
288  void MergeXML::mergeAttribute( TiXmlElement* element, TiXmlElement* domElement ) {
289 
290  // loop through all attributs of given node
291  TiXmlAttribute* loopAttribute = element->FirstAttribute() ;
292  while ( loopAttribute )
293  {
294  // which Attribut
295  std::string attName = loopAttribute->Name() ;
296 
297  // debug information
298  //std::cout << " loopAttribut " << attName ;
299 
300  // get same attribute in dominant element
301  const char* domAttribute = domElement->Attribute( attName ) ;
302 
303  if( domAttribute == NULL ) {
304 
305  // add to domElement
306  domElement->SetAttribute( attName, loopAttribute->Value() ) ;
307 
308  // debug information
309  //std::cout << " added." << std::endl ;
310  }
311  else {
312 
313  // debug information
314  //std::cout << " exists." << std::endl ;
315  }
316 
317  // go to next Attribute
318  loopAttribute = loopAttribute->Next() ;
319  }
320  }
321 
322 } //namespace gear
323 
324 
325 
326 
327 
328 
329 
bool SaveFile() const
Save a file using the current document value. Returns true if successful.
Definition: tinyxml.cc:933
bool mergeFiles(const std::string &fileName)
merges files
Definition: MergeXML.cc:36
bool LoadFile(TiXmlEncoding encoding=TIXML_DEFAULT_ENCODING)
Load a file using the current document value.
Definition: tinyxml.cc:921
const char * Value() const
The meaning of &#39;value&#39; changes for the specific type of TiXmlNode.
Definition: tinyxml.h:437
const TiXmlUnknown * ToUnknown() const
Cast to a more defined type. Will return null not of the requested type.
Definition: tinyxml.h:619
Always the top level node.
Definition: tinyxml.h:1154
const TiXmlComment * ToComment() const
Cast to a more defined type. Will return null not of the requested type.
Definition: tinyxml.h:618
The parent class for everything in the Document Object Model.
Definition: tinyxml.h:370
TiXmlNode * InsertEndChild(const TiXmlNode &addThis)
Add a new node related to this.
Definition: tinyxml.cc:218
bool setFile1(const std::string &fileName)
Sets first filename returns true if file can be read.
Definition: MergeXML.cc:9
const TiXmlNode * FirstChild() const
The first child of this node. Will be null if there are no children.
Definition: tinyxml.h:466
const TiXmlNode * IterateChildren(const TiXmlNode *previous) const
An alternate way to walk the children of a node.
Definition: tinyxml.cc:376
bool setFile2(const std::string &fileName)
Sets second filename returns true if file can be read.
Definition: MergeXML.cc:17
const TiXmlText * ToText() const
Cast to a more defined type. Will return null not of the requested type.
Definition: tinyxml.h:620