using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
namespace xmlTools
{
class XmlTools
{
private XmlDocument xdoc;
private string posElement, posParentElement;
private bool noBackups;
/// Our constructor
///
///
///
///
///
public XmlTools(string posElement, string posParentElement = "", bool noBackups = false)
{
this.posElement = posElement;
this.posParentElement = posParentElement;
this.noBackups = noBackups;
}
///
/// Replace all values of a element by another value
///
///
///
public void replaceAll(string file, string value, string valuePositions = "")
{
if (!this.noBackups)
{
Util.backupFile(file);
}
loadXmlFile(file);
List myElements = new List();
Util.getAllSpecificElements(xdoc.DocumentElement, ref myElements, this.posElement, this.posParentElement); //Returns all after "Oni" element
if (!String.IsNullOrEmpty(valuePositions))
{
checkValidSpecificPositions(valuePositions, value, myElements[0].InnerText);
}
foreach (XmlNode element in myElements)
{
if (element.Name == posElement)
{
if (!String.IsNullOrEmpty(posParentElement) && element.ParentNode.Name != posParentElement)
{
continue;
}
if (String.IsNullOrEmpty(valuePositions)) //replace every value for the new
{
element.InnerText = value;
}
else //replace only the specified positions by the specified values of each dimension
{
element.InnerText = replaceSpecificPositions(element.InnerText, value, valuePositions);
}
}
}
saveXmlFile(file);
}
///
/// Add values in an element
///
///
///
public void addValues(string file, string values)
{
if (!this.noBackups)
{
Util.backupFile(file);
}
loadXmlFile(file);
XmlTextValue myInputValues = new XmlTextValue(values);
List myElements = new List();
Util.getAllSpecificElements(xdoc.DocumentElement, ref myElements, this.posElement, this.posParentElement); //Returns all after "Oni" element
foreach (XmlNode element in myElements)
{
if (element.Name == posElement)
{
if (!String.IsNullOrEmpty(posParentElement) && element.ParentNode.Name != posParentElement)
{
continue;
}
XmlTextValue myXmlSubValues = new XmlTextValue(element.InnerText);
foreach (String myInputValue in myInputValues.myValues)
{
bool alreadyExists = false;
foreach (String myXmlSubValue in myXmlSubValues.myValues)
{
//It already exists in the xml??
if (myInputValue == myXmlSubValue)
{
alreadyExists = true;
break;
}
}
//if it doesn't exists already let's add it
if (!alreadyExists)
{
element.InnerText += " " + myInputValue;
}
}
}
}
saveXmlFile(file);
}
///
/// Replaces a value by another
///
///
///
public void replaceValue(string file, string oldValue, string newValue)
{
if (!this.noBackups)
{
Util.backupFile(file);
}
loadXmlFile(file);
List myElements = new List();
Util.getAllSpecificElements(xdoc.DocumentElement, ref myElements, this.posElement, this.posParentElement); //Returns all after "Oni" element
foreach (XmlNode element in myElements)
{
if (element.Name == posElement)
{
if (!String.IsNullOrEmpty(posParentElement) && element.ParentNode.Name != posParentElement)
{
continue;
}
XmlTextValue myXmlSubValues = new XmlTextValue(element.InnerText);
for (int i = 0; i < myXmlSubValues.myValues.Count; i++)
{
//Found a match with the old value?
if (myXmlSubValues.myValues[i] == oldValue)
{
//replace with the new match
myXmlSubValues.myValues[i] = newValue;
}
}
element.InnerText = myXmlSubValues.ToString();
}
}
saveXmlFile(file);
}
///
/// Remove values in an element
///
///
///
public void removeValues(string file, string values)
{
if (!this.noBackups)
{
Util.backupFile(file);
}
loadXmlFile(file);
XmlTextValue myInputValues = new XmlTextValue(values);
List myElements = new List();
Util.getAllSpecificElements(xdoc.DocumentElement, ref myElements, this.posElement, this.posParentElement); //Returns all after "Oni" element
foreach (XmlNode element in myElements)
{
if (element.Name == posElement)
{
if (!String.IsNullOrEmpty(posParentElement) && element.ParentNode.Name != posParentElement)
{
continue;
}
XmlTextValue myXmlSubValues = new XmlTextValue(element.InnerText);
foreach (String myInputValue in myInputValues.myValues)
{
for (int i = 0; i < myXmlSubValues.myValues.Count; i++)
{
//It already exists in the xml?
if (myInputValue == myXmlSubValues.myValues[i])
{
//remove it
myXmlSubValues.myValues.RemoveAt(i);
break;
}
}
}
element.InnerText = myXmlSubValues.myValues.ToString();
}
}
saveXmlFile(file);
}
///
/// Change a value of element (updating all the chain)
///
///
///
///
public void changeValue(string file, string newValue, string valueRelation = "", string valuePositions = "")
{
if (!this.noBackups)
{
Util.backupFile(file);
}
loadXmlFile(file);
XmlNumberValue xmlLastPos = null, newXmlLastPos = null;
List myElements = new List();
Util.getAllSpecificElements(xdoc.DocumentElement, ref myElements, this.posElement, this.posParentElement); //Returns all after "Oni" element
if (String.IsNullOrEmpty(valuePositions))
{
newXmlLastPos = new XmlNumberValue(newValue);
}
else //If specific positions to be changed are specified, just associate the newLastPos with the first replaced in the specific positions by the specific values
{
newXmlLastPos = new XmlNumberValue(replaceSpecificPositions(myElements[0].InnerText, newValue, valuePositions));
}
if (!String.IsNullOrEmpty(valuePositions))
{
checkValidSpecificPositions(valuePositions, newValue, myElements[0].InnerText);
}
foreach (XmlNode element in myElements)
{
if (element.Name == this.posElement && (String.IsNullOrEmpty(this.posParentElement) || this.posParentElement == element.ParentNode.Name))
{
XmlNumberValue xmlCurrValue = new XmlNumberValue(element.InnerText);
if (xmlLastPos!=null)
{
newXmlLastPos = XmlNumberValue.sum(newXmlLastPos, XmlNumberValue.difference(xmlCurrValue, xmlLastPos));
element.InnerText = newXmlLastPos.ToString();
xmlLastPos = xmlCurrValue;
}
else
{ // first time just assign to last value
if (!String.IsNullOrEmpty(valueRelation))
{
newXmlLastPos = XmlNumberValue.difference(newXmlLastPos, XmlNumberValue.difference(new XmlNumberValue(valueRelation), xmlCurrValue));
}
xmlLastPos = xmlCurrValue;
element.InnerText = newXmlLastPos.ToString();
}
}
}
saveXmlFile(file);
}
///
/// Invert the values of a element name (inverts all the chain)
///
///
public void invert(string file)
{
if (!this.noBackups)
{
Util.backupFile(file);
}
loadXmlFile(file);
//Inverting the element order
List invertedOrder = new List();
List myElements = new List();
Util.getAllSpecificElements(this.xdoc.DocumentElement, ref myElements, this.posElement, this.posParentElement);
//Read all and save to the list
foreach (XmlNode element in myElements) //Returns all after "Oni" element
{
invertedOrder.Add(element.InnerText);
}
//Let's start taking from the list to new xml file (inverted order)
int count = 0;
foreach (XmlNode element in myElements) //Returns all after "Oni" element
{
if (element.Name == posElement)
{
element.InnerText = invertedOrder[invertedOrder.Count - 1 - count];
count++;
}
}
saveXmlFile(file);
}
private void loadXmlFile(string file)
{
this.xdoc = new XmlDocument();
this.xdoc.Load(file);
}
private void saveXmlFile(string file)
{
this.xdoc.Save(file);
}
private void checkValidSpecificPositions(string valuePositions, string value, string firstElement)
{
XmlNumberValue testValuePositions = new XmlNumberValue(valuePositions);
XmlNumberValue testValue = new XmlNumberValue(value);
XmlNumberValue testFirstRealValue = new XmlNumberValue(firstElement);
if (testValuePositions.myValues.Count != testValue.myValues.Count) //Check if there are the same number of positions for the same number of dimensions to replace
{
Program.printAppError(Program.appErrors.NUMBER_VALUES_TO_REPLACE_NE_AVAILABLE_VALUES, "The number of values to replace must be the same of the number of specified positions.", true);
}
foreach (int pos in testValuePositions.myValues) //converts automatically from double to int
{
if (pos > testFirstRealValue.myValues.Count - 1 || pos < 0) //Are positions valid for the current values? //-1 because starts at 0
{
Program.printAppError(Program.appErrors.INVALID_POSITIONS_RANGE, "The positions values are not in the range of the value to replace (pos index < 0 or > newValueIndexesNumber).", true);
}
}
}
private string replaceSpecificPositions(string currXmlValue, string values, string valuePositions)
{
XmlNumberValue currentValue = new XmlNumberValue(currXmlValue);
XmlNumberValue positionsValues = new XmlNumberValue(valuePositions);
XmlNumberValue newValues = new XmlNumberValue(values);
for (int i = 0; i < positionsValues.myValues.Count; i++)
{
int posToChange = (int)positionsValues.myValues[i];
currentValue.myValues[posToChange] = newValues.myValues[i];
}
return currentValue.ToString();
}
}
}