source: XmlTools2/trunk/xmltools.cpp@ 920

Last change on this file since 920 was 920, checked in by s10k, 11 years ago

more fixes and updated examples

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