source: XmlTools2/trunk/xmltools.cpp@ 1072

Last change on this file since 1072 was 1055, checked in by s10k, 8 years ago

XmlTools 2.0c

File size: 14.8 KB
RevLine 
[906]1#include "xmltools.h"
2
[920]3// Filters constructor
[923]4XmlTools::XmlTools(QString filesWildcard, XmlFilter filter, bool noBackups, bool noVerbose)
[906]5{
6 this->filesToProcess=UtilXmlTools::getAllXmlFilesByWildcard(filesWildcard);
7 this->filters=filter;
8 this->backupsEnabled=!noBackups;
[923]9 this->verboseEnabled=!noVerbose;
[906]10
[910]11 if(this->filesToProcess.isEmpty()){
[906]12 UtilXmlTools::displayErrorMessage("Loading xml files","No XML files were found for the wildcard: "+filesWildcard);
13 }
14}
15
[920]16// XPath constructor
[923]17XmlTools::XmlTools(QString filesWildcard, QString xPathExpression, bool noBackups, bool noVerbose)
[920]18{
19 this->filesToProcess=UtilXmlTools::getAllXmlFilesByWildcard(filesWildcard);
20 this->xPathExpression=xPathExpression;
21 this->backupsEnabled=!noBackups;
[923]22 this->verboseEnabled=!noVerbose;
[920]23}
24
[906]25// Adds new values to an element
26void XmlTools::addValues(QString newValues){
27
[1055]28 try{
29 // Process all XmlFiles
30 for(int i=0; i<this->filesToProcess.size(); i++){
[906]31
[1055]32 QStringList newValuesList, currValuesList;
33 QList<pugi::xml_node> elements;
[906]34
[1055]35 UtilXmlTools::loadXmlFile(this->filesToProcess[i],this->document,this->rootNode,this->backupsEnabled,this->verboseEnabled,"add-values");
[906]36
[1055]37 newValuesList=Util::qStringListFromSpacedString(newValues);
[906]38
[1055]39 // Check how the elements will be fetched via element name or xpath expression
40 if(this->xPathExpression==""){
41 UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
42 }
43 else{
44 UtilXmlTools::getAllXpathElements(this->xPathExpression,this->document,elements);
45 }
[920]46
[1055]47 for(int j=0; j<elements.size(); j++){
[906]48
[1055]49 currValuesList=Util::qStringListFromSpacedString(Util::toQString(elements[j].text().as_string())); // convert each element in a list (uses space as separator)
[906]50
[1055]51 for(int k=0; k<newValuesList.size(); k++){
52 if(currValuesList.contains(newValuesList[k])){ // If the current element already contains this value proceed to the next
53 continue;
54 }
55
56 elements[j].text()=QString(Util::toQString(elements[j].text().as_string()) + " " + newValuesList[k]).toUtf8().constData(); // If it doesn't exists yet let's add it
[906]57 }
[1055]58 }
[906]59
[1055]60 UtilXmlTools::saveXmlFile(this->filesToProcess[i],this->document,"add-values");
[906]61 }
62 }
[1055]63 catch(const std::exception &e){
64 UtilXmlTools::displayErrorMessage("add-values", QString("An exception was caught: ") + e.what());
65 }
[906]66
67 UtilXmlTools::displaySuccessMessage(this->filesToProcess.size(), "add-values");
68
69}
70
71void XmlTools::removeValues(QString valuesToRemove){
72
[1055]73 try{
74 // Process all XmlFiles
75 for(int i=0; i<this->filesToProcess.size(); i++){
[906]76
[1055]77 QList<pugi::xml_node> elements;
78 QStringList valuesToRemoveList, currValuesList;
79 bool elementChanged=false;
[906]80
[1055]81 UtilXmlTools::loadXmlFile(this->filesToProcess[i],this->document,this->rootNode,this->backupsEnabled, this->verboseEnabled, "remove-values");
[906]82
[1055]83 // Check how the elements will be fetched via element name or xpath expression
84 if(this->xPathExpression==""){
85 UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
86 }
87 else{
88 UtilXmlTools::getAllXpathElements(this->xPathExpression,this->document,elements);
89 }
[906]90
[1055]91 valuesToRemoveList=Util::qStringListFromSpacedString(valuesToRemove);
[906]92
[1055]93 for(int j=0; j<elements.size(); j++){ // O(3)... Optimization may be necessary.
94 currValuesList=Util::qStringListFromSpacedString(Util::toQString(elements[j].text().as_string())); // convert each element in a list (uses space as separator)
[906]95
[1055]96 for(int k=0; k<currValuesList.size(); k++){
97 for(int m=0; m<valuesToRemoveList.size(); m++){
98 if(currValuesList[k]==valuesToRemoveList[m]){
99 currValuesList[k]=""; // flag to deletion
100 elementChanged=true;
101 }
[906]102 }
103 }
[1055]104
105 if(elementChanged){ // If curr element changed update the XML
106 currValuesList.removeAll(""); // remove all files flagged to deletion
107 elements[j].text()=currValuesList.join(' ').toUtf8().constData();
108 elementChanged=false;
109 }
[906]110 }
111
[1055]112 UtilXmlTools::saveXmlFile(this->filesToProcess[i],this->document, "remove-values");
[906]113 }
114 }
[1055]115 catch(const std::exception &e){
116 UtilXmlTools::displayErrorMessage("remove-values", QString("An exception was caught: ") + e.what());
117 }
[906]118
119 UtilXmlTools::displaySuccessMessage(this->filesToProcess.size(),"remove-values");
120}
121
122void XmlTools::replaceValue(QString oldValue, QString newValue){
123
[1055]124 try{
125 // Process all XmlFiles
126 for(int i=0; i<this->filesToProcess.size(); i++){
[906]127
[1055]128 QList<pugi::xml_node> elements;
129 QStringList currValuesList;
130 bool elementChanged=false;
[906]131
[1055]132 UtilXmlTools::loadXmlFile(this->filesToProcess[i],this->document,this->rootNode,this->backupsEnabled, this->verboseEnabled, "replace-value");
[906]133
[1055]134 // Check how the elements will be fetched via element name or xpath expression
135 if(this->xPathExpression==""){
136 UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
137 }
138 else{
139 UtilXmlTools::getAllXpathElements(this->xPathExpression,this->document,elements);
140 }
[906]141
[1055]142 for(int j=0; j<elements.size(); j++){
143 currValuesList=Util::qStringListFromSpacedString(Util::toQString(elements[j].text().as_string())); // convert each element in a list (uses space as separator)
[906]144
[1055]145 for(int k=0; k<currValuesList.size(); k++){
146 if(currValuesList[k]==oldValue){ // Found a match with the old value?
147 currValuesList[k]=newValue; // If found replace it with the new value
148 elementChanged=true;
149 }
[906]150 }
[1055]151
152 if(elementChanged){ // If curr element changed update the XML
153 elements[j].text()=currValuesList.join(" ").toUtf8().constData();
154 }
155 elementChanged=false;
[906]156 }
157
[1055]158 UtilXmlTools::saveXmlFile(this->filesToProcess[i],this->document, "replace-value");
[906]159 }
160 }
[1055]161 catch(const std::exception &e){
162 UtilXmlTools::displayErrorMessage("replace-value", QString("An exception was caught: ") + e.what());
163 }
[906]164
165 UtilXmlTools::displaySuccessMessage(this->filesToProcess.size(), "replace-value");
166}
167
168// Replaces all current values of an element by another (can be specified only specific positions)
169void XmlTools::replaceAll(QString value, QString valuePositions){
170
[1055]171 try{
172 // Process all XmlFiles
173 for(int i=0; i<this->filesToProcess.size(); i++){
[906]174
[1055]175 QList<pugi::xml_node> elements;
[906]176
[1055]177 UtilXmlTools::loadXmlFile(this->filesToProcess[i],this->document,this->rootNode,this->backupsEnabled, this->verboseEnabled, "replace-all");
[906]178
[1055]179 // Check how the elements will be fetched via element name or xpath expression
180 if(this->xPathExpression==""){
181 UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
182 }
183 else{
184 UtilXmlTools::getAllXpathElements(this->xPathExpression,this->document,elements);
185 }
[906]186
187
[1055]188 // Let's start the override
189 for(int j=0; j<elements.size(); j++){
190 if(valuePositions!=""){
191 elements[j].text()=replaceSpecificPositions(value, Util::toQString(elements[j].text().as_string()),valuePositions).toUtf8().constData();
192 }
193 else{
194 elements[j].text()=value.toUtf8().constData();
195 }
[906]196 }
[1055]197
198 UtilXmlTools::saveXmlFile(this->filesToProcess[i],this->document, "replace-all");
[906]199 }
200 }
[1055]201 catch(const std::exception &e){
202 UtilXmlTools::displayErrorMessage("replace-all", QString("An exception was caught: ") + e.what());
203 }
[906]204
205 UtilXmlTools::displaySuccessMessage(this->filesToProcess.size(), "replace-all");
206}
207
208// Update a set of XML elements values based in the difference between the old and new value
209// This can be used in multiple files if the difference between one file and other are the same e.g. increment to all current object positions 100 in y (A difference of -100).
210// E.g. oldValue=5 , newValue=7; diffBetweenOldAndNewValue=-2
211void XmlTools::updateElements(QString diffBetweenOldAndNewValue){
212
[1055]213 try{
214 // Process all XmlFiles
215 for(int i=0; i<this->filesToProcess.size(); i++){
[906]216
[1055]217 QList<pugi::xml_node> elements;
218 MultiDimVar lastXmlValue(0); // inicialize with any value or dimension
219 MultiDimVar currXmlValue(0);
220 MultiDimVar newXmlValue(0); // value that will update currValue
[906]221
[1055]222 UtilXmlTools::loadXmlFile(this->filesToProcess[i],this->document,this->rootNode,this->backupsEnabled,this->verboseEnabled, "update-elements");
[906]223
[1055]224 // Check how the elements will be fetched via element name or xpath expression
225 if(this->xPathExpression==""){
226 UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
227 }
228 else{
229 UtilXmlTools::getAllXpathElements(this->xPathExpression,this->document,elements);
230 }
[906]231
[1055]232 if(elements.size() > 0){
[906]233
[1055]234 lastXmlValue=MultiDimVar(Util::toQString(elements[0].text().as_string())); // the lastXmlValue will begin to be the first one of the node
235 newXmlValue=MultiDimVar::sub(lastXmlValue, MultiDimVar(diffBetweenOldAndNewValue));
236 elements[0].text() = newXmlValue.toString().toUtf8().constData(); // update the first element with the new one already
[906]237
[1055]238 // If we have more than 1 element
239 if(elements.size()>1){
240 currXmlValue=MultiDimVar(Util::toQString(elements[1].text().as_string())); // the currXmlValue will begin to be the second one of the node
[906]241
[1055]242 // Let's start the node update
243 for(int j=1; j<elements.size()-1; j++){ // We start in 1 because the 0 is already saved in lastXmlValue // -1 because we will also work with the next one in the current
[906]244
[1055]245 newXmlValue=MultiDimVar::sum(newXmlValue,MultiDimVar::sub(currXmlValue,lastXmlValue));
246 elements[j].text() = newXmlValue.toString().toUtf8().constData(); // update element with the new value
247 lastXmlValue=currXmlValue;
248 currXmlValue=MultiDimVar(Util::toQString(elements[j+1].text().as_string()));
[906]249
[1055]250 }
[906]251
[1055]252 // To update too last element (avoid out of bound because i+1)
253 newXmlValue=MultiDimVar::sum(newXmlValue,MultiDimVar::sub(currXmlValue,lastXmlValue));
254 elements[elements.size()-1].text() = newXmlValue.toString().toUtf8().constData(); // update element with the new value
255 }
256 }
257
258 UtilXmlTools::saveXmlFile(this->filesToProcess[i],this->document, "update-elements");
259 }
[906]260 }
[1055]261 catch(const std::exception &e){
262 UtilXmlTools::displayErrorMessage("update-elements", QString("An exception was caught: ") + e.what());
263 }
[906]264
[1055]265 UtilXmlTools::displaySuccessMessage(this->filesToProcess.size(),"update-elements");
[906]266
267}
268
269// Invert a set of XML elements with specified name (and optionally a parent name)
270void XmlTools::invertElements(){
271
[1055]272 try{
273 // Process all XmlFiles
274 for(int i=0; i<this->filesToProcess.size(); i++){
275 UtilXmlTools::loadXmlFile(this->filesToProcess[i],this->document,this->rootNode,this->backupsEnabled, this->verboseEnabled, "invert-elements");
[906]276
[1055]277 QList<pugi::xml_node> elements;
278 QStringList invertedElements; //Inverting the element order
[906]279
[1055]280 // Check how the elements will be fetched via element name or xpath expression
281 if(this->xPathExpression==""){
282 UtilXmlTools::getAllNamedElements(this->rootNode,elements,this->filters);
283 }
284 else{
285 UtilXmlTools::getAllXpathElements(this->xPathExpression,this->document,elements);
286 }
[906]287
[1055]288 // Read all elements and save to the list
289 for(int j=elements.size()-1; j>=0; j--){
290 invertedElements << Util::toQString(elements[j].text().as_string());
291 }
[906]292
[1055]293 // Override the tree with the inverted order
294 for(int j=0; j<elements.size(); j++){
295 elements[j].text()= invertedElements[j].toUtf8().constData();
296 }
297
298 UtilXmlTools::saveXmlFile(this->filesToProcess[i],this->document, "invert-elements");
[906]299 }
300 }
[1055]301 catch(const std::exception &e){
302 UtilXmlTools::displayErrorMessage("invert-elements", QString("An exception was caught: ") + e.what());
303 }
[906]304
305 UtilXmlTools::displaySuccessMessage(this->filesToProcess.size(),"invert-elements");
306
307}
308
309// Replaces specific values (given the position) for a new value
310// [ currValues / positionsToReplaced are strings with composed by another strings space separated ]
311// Returns a new string (space separated) will values replaced
312QString XmlTools::replaceSpecificPositions(const QString &newValue, const QString &currValues, const QString &positionsToReplace){
313
314 QList<int> positionsToReplaceList;
315 QStringList currValuesList;
316
317 positionsToReplaceList=Util::qListIntFromSpacedString(positionsToReplace);
318 currValuesList=Util::qStringListFromSpacedString(currValues);
319
320 // Make some validation before the replacing
321 if(currValuesList.size()<positionsToReplaceList.size()){
322 UtilXmlTools::displayErrorMessage("replaceSpecificPositions","There are more positions to replace than the current xml values.");
323 }
324
325 foreach(int pos, positionsToReplaceList){
326 if(pos>currValuesList.size()-1 || pos < 0){ //Are positions valid for the current values? //-1 because starts at 0
327 UtilXmlTools::displayErrorMessage("replaceSpecificPositions","One or more of the specified positions to replace are out of range.");
328 }
329 }
330 //
331
332 // Finally replace the specified values
333 foreach(int pos, positionsToReplaceList){
334 currValuesList[pos]=newValue;
335 }
336
337 return currValuesList.join(" ");
338
339}
Note: See TracBrowser for help on using the repository browser.