source: s10k/XmlTools/xmltools.cpp@ 1116

Last change on this file since 1116 was 1073, checked in by s10k, 7 years ago

added XML Tools latest version (2.0d) and s10k's common libs

File size: 14.8 KB
Line 
1#include "xmltools.h"
2
3// Filters constructor
4XmlTools::XmlTools(QString filesWildcard, XmlFilter filter, bool noBackups, bool noVerbose)
5{
6 this->filesToProcess=UtilXmlTools::getAllXmlFilesByWildcard(filesWildcard);
7 this->filters=filter;
8 this->backupsEnabled=!noBackups;
9 this->verboseEnabled=!noVerbose;
10
11 if(this->filesToProcess.isEmpty()){
12 UtilXmlTools::displayErrorMessage("Loading xml files","No XML files were found for the wildcard: "+filesWildcard);
13 }
14}
15
16// XPath constructor
17XmlTools::XmlTools(QString filesWildcard, QString xPathExpression, bool noBackups, bool noVerbose)
18{
19 this->filesToProcess=UtilXmlTools::getAllXmlFilesByWildcard(filesWildcard);
20 this->xPathExpression=xPathExpression;
21 this->backupsEnabled=!noBackups;
22 this->verboseEnabled=!noVerbose;
23}
24
25// Adds new values to an element
26void XmlTools::addValues(QString newValues){
27
28 try{
29 // Process all XmlFiles
30 for(int i=0; i<this->filesToProcess.size(); i++){
31
32 QStringList newValuesList, currValuesList;
33 QList<pugi::xml_node> elements;
34
35 UtilXmlTools::loadXmlFile(this->filesToProcess[i],this->document,this->rootNode,this->backupsEnabled,this->verboseEnabled,"add-values");
36
37 newValuesList=UtilXmlTools::qStringListFromSpacedString(newValues);
38
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 }
46
47 for(int j=0; j<elements.size(); j++){
48
49 currValuesList=UtilXmlTools::qStringListFromSpacedString(QSTR_TO_CSTR(elements[j].text().as_string())); // convert each element in a list (uses space as separator)
50
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() = QSTR_TO_CSTR( QString(elements[j].text().as_string()) + " " + newValuesList[k] ); // If it doesn't exists yet let's add it
57 }
58 }
59
60 UtilXmlTools::saveXmlFile(this->filesToProcess[i],this->document,"add-values");
61 }
62 }
63 catch(const std::exception &e){
64 UtilXmlTools::displayErrorMessage("add-values", QString("An exception was caught: ") + e.what());
65 }
66
67 UtilXmlTools::displaySuccessMessage(this->filesToProcess.size(), "add-values");
68
69}
70
71void XmlTools::removeValues(QString valuesToRemove){
72
73 try{
74 // Process all XmlFiles
75 for(int i=0; i<this->filesToProcess.size(); i++){
76
77 QList<pugi::xml_node> elements;
78 QStringList valuesToRemoveList, currValuesList;
79 bool elementChanged=false;
80
81 UtilXmlTools::loadXmlFile(this->filesToProcess[i],this->document,this->rootNode,this->backupsEnabled, this->verboseEnabled, "remove-values");
82
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 }
90
91 valuesToRemoveList=UtilXmlTools::qStringListFromSpacedString(valuesToRemove);
92
93 for(int j=0; j<elements.size(); j++){ // O(3)... Optimization may be necessary.
94 currValuesList=UtilXmlTools::qStringListFromSpacedString(QSTR_TO_CSTR(elements[j].text().as_string())); // convert each element in a list (uses space as separator)
95
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 }
102 }
103 }
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 }
110 }
111
112 UtilXmlTools::saveXmlFile(this->filesToProcess[i],this->document, "remove-values");
113 }
114 }
115 catch(const std::exception &e){
116 UtilXmlTools::displayErrorMessage("remove-values", QString("An exception was caught: ") + e.what());
117 }
118
119 UtilXmlTools::displaySuccessMessage(this->filesToProcess.size(),"remove-values");
120}
121
122void XmlTools::replaceValue(QString oldValue, QString newValue){
123
124 try{
125 // Process all XmlFiles
126 for(int i=0; i<this->filesToProcess.size(); i++){
127
128 QList<pugi::xml_node> elements;
129 QStringList currValuesList;
130 bool elementChanged=false;
131
132 UtilXmlTools::loadXmlFile(this->filesToProcess[i],this->document,this->rootNode,this->backupsEnabled, this->verboseEnabled, "replace-value");
133
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 }
141
142 for(int j=0; j<elements.size(); j++){
143 currValuesList=UtilXmlTools::qStringListFromSpacedString(QSTR_TO_CSTR(elements[j].text().as_string())); // convert each element in a list (uses space as separator)
144
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 }
150 }
151
152 if(elementChanged){ // If curr element changed update the XML
153 elements[j].text()=currValuesList.join(" ").toUtf8().constData();
154 }
155 elementChanged=false;
156 }
157
158 UtilXmlTools::saveXmlFile(this->filesToProcess[i],this->document, "replace-value");
159 }
160 }
161 catch(const std::exception &e){
162 UtilXmlTools::displayErrorMessage("replace-value", QString("An exception was caught: ") + e.what());
163 }
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
171 try{
172 // Process all XmlFiles
173 for(int i=0; i<this->filesToProcess.size(); i++){
174
175 QList<pugi::xml_node> elements;
176
177 UtilXmlTools::loadXmlFile(this->filesToProcess[i],this->document,this->rootNode,this->backupsEnabled, this->verboseEnabled, "replace-all");
178
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 }
186
187
188 // Let's start the override
189 for(int j=0; j<elements.size(); j++){
190 if(valuePositions!=""){
191 elements[j].text()=replaceSpecificPositions(value, QSTR_TO_CSTR(elements[j].text().as_string()),valuePositions).toUtf8().constData();
192 }
193 else{
194 elements[j].text()=value.toUtf8().constData();
195 }
196 }
197
198 UtilXmlTools::saveXmlFile(this->filesToProcess[i],this->document, "replace-all");
199 }
200 }
201 catch(const std::exception &e){
202 UtilXmlTools::displayErrorMessage("replace-all", QString("An exception was caught: ") + e.what());
203 }
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
213 try{
214 // Process all XmlFiles
215 for(int i=0; i<this->filesToProcess.size(); i++){
216
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
221
222 UtilXmlTools::loadXmlFile(this->filesToProcess[i],this->document,this->rootNode,this->backupsEnabled,this->verboseEnabled, "update-elements");
223
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 }
231
232 if(elements.size() > 0){
233
234 lastXmlValue=MultiDimVar(QSTR_TO_CSTR(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
237
238 // If we have more than 1 element
239 if(elements.size()>1){
240 currXmlValue=MultiDimVar(QSTR_TO_CSTR(elements[1].text().as_string())); // the currXmlValue will begin to be the second one of the node
241
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
244
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(QSTR_TO_CSTR(elements[j+1].text().as_string()));
249
250 }
251
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 }
260 }
261 catch(const std::exception &e){
262 UtilXmlTools::displayErrorMessage("update-elements", QString("An exception was caught: ") + e.what());
263 }
264
265 UtilXmlTools::displaySuccessMessage(this->filesToProcess.size(),"update-elements");
266
267}
268
269// Invert a set of XML elements with specified name (and optionally a parent name)
270void XmlTools::invertElements(){
271
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");
276
277 QList<pugi::xml_node> elements;
278 QStringList invertedElements; //Inverting the element order
279
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 }
287
288 // Read all elements and save to the list
289 for(int j=elements.size()-1; j>=0; j--){
290 invertedElements << QSTR_TO_CSTR(elements[j].text().as_string());
291 }
292
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");
299 }
300 }
301 catch(const std::exception &e){
302 UtilXmlTools::displayErrorMessage("invert-elements", QString("An exception was caught: ") + e.what());
303 }
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=UtilXmlTools::qListIntFromSpacedString(positionsToReplace);
318 currValuesList=UtilXmlTools::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.