Introduction
This framework provides an easy way to access XML files with support for inserting, updating, deleting, and selecting by querying the XML like querying SQL.
Using the Code
I'll start by writing simple lines of code that demonstrate the operations of inserting, updating, deleting, and selecting, and then show the results in an XML file.
Here is how we create an XML file and access an object:
static void Main(string[] args)
{
BaseDataAccess access =
new BaseDataAccess("D:/xmltest.xml", "Objects");
}
Simple Inserting
The Insert
method takes an object of type BaseDataObject
as a parameter, which contains the name of the node, the value, the attributes, and a list of children which are of the same type as well.
access.Insert(new BaseDataObject("type", "human")).Execute();
access.Insert(new BaseDataObject("type", "animal")).Execute();
Simple Selecting
You can query the XML to select specific nodes:
List<BaseDataObject> dataList = access.Select("type").
Where("type").
IsEqualTo("animal").
ExecuteSelect<BaseDataObject>();
for (int i = 0; i < dataList.Count; i++)
{
Console.WriteLine(dataList[i].Name + " : " + dataList[i].Value);
}
Updating
It is also easy to update specific nodes:
access.Update("type").Set("type").EqualTo("animal").
Where("type").IsEqualTo("human").Execute();
Deleting
And here is how we delete:
access.Delete("type").Where("type").IsEqualTo("animal").Execute();
Advanced Inserting
The way to insert children of children is to make a list of BaseDataObject
s and insert them in the list of the children of another BaseDataObject
. (The best way to do this is recursively.) The following code inserts three levels of children in depth:
static void Main(string[] args)
{
BaseDataAccess access =
new BaseDataAccess("test.xml", "objects");
List<BaseDataObject> parents = new List<BaseDataObject>();
for (int i = 0; i < 5; i++)
{
parents.Add(new BaseDataObject("Parent", MakeChilds(5)));
}
BaseDataObject parentOfParents =
new BaseDataObject("GrandParent", parents);
access.Insert(parentOfParents).Execute();
Console.WriteLine(access.XmlString);
Console.ReadLine();
}
private static List<BaseDataObject> MakeChilds(int count)
{
List<BaseDataObject> childs = new List<BaseDataObject>();
for (int i = 0; i < count; i++)
{
childs.Add(new BaseDataObject("N" + i.ToString(),
"V " + i.ToString()));
}
return childs;
}
Advanced Selecting
Here is how we select any child in the selected objects, recursively, with the method PrintObject(obj)
:
static void Main(string[] args)
{
BaseDataAccess access = new BaseDataAccess("test.xml", "objects");
List<BaseDataObject> parents = new List<BaseDataObject>();
for (int i = 0; i < 5; i++)
{
parents.Add(new BaseDataObject("Parent", MakeChilds(5)));
}
BaseDataObject parentOfParents = new BaseDataObject("GrandParent", parents);
access.Insert(parentOfParents).Execute();
List<BaseDataObject> objects =
access.Select("GrandParent").ExecuteSelect<BaseDataObject>();
for (int i = 0; i < objects.Count; i++)
{
PrintObject(objects[i]);
}
Console.ReadLine();
}
private static List<BaseDataObject> MakeChilds(int count)
{
List<BaseDataObject> childs = new List<BaseDataObject>();
for (int i = 0; i < count; i++)
{
childs.Add(new BaseDataObject("N" + i.ToString(),
" V" + i.ToString() + " "));
}
return childs;
}
private static void PrintObject(BaseDataObject obj)
{
if (obj.Childs.Count > 0)
{
Console.WriteLine(obj.Name + " >");
for (int i = 0; i < obj.Childs.Count; i++)
{
PrintObject(obj.Childs[i]);
}
}
else
{
Console.WriteLine(obj.Name + " : " + obj.Value);
}
}
Inserting Simple Objects
If you want to quickly save the properties of an object in XML (simple serialization), there is another generic Insert
method which takes any object as a parameter and inserts all the properties of type string
or int
in the XML file.
class MyClass
{
public MyClass()
{
Age = 20;
FirstName = "Islam";
LastName = "Eldemery";
Address = "Egypt, Cairo, bla bla bla";
}
public int Age { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
}
class Program
{
static void Main(string[] args)
{
MyClass obj = new MyClass();
BaseDataAccess access = new BaseDataAccess("test.xml", "objects");
access.Insert<MyClass>(obj).Execute();
Console.WriteLine(access.XmlString);
Console.ReadLine();
}
}
So Far So Good, Let's Dig Deeper..
Overriding the Virtual Methods in the Base Class
Imagine you want to encrypt the XML after inserting, and decrypt it before selecting. This can be easily done by overriding the base methods as follows:
class XmlAccess : BaseDataAccess
{
XMLEncryptor encryptor;
public XmlAccess(string path, string rootElement)
: base(path, rootElement)
{
encryptor = new XMLEncryptor(path);
}
public override bool Execute()
{
bool executed = base.Execute();
encryptor.Encrypt(base._objectToInsert.Name, "myKey");
return executed;
}
public override List<T> ExecuteSelect<T>()
{
encryptor.Decrypt("myKey");
return base.ExecuteSelect<T>();
}
}
Select All Nodes
You can also select all the nodes in the root node with all children and children of children, in one line of code:
List<BaseDataObject> objects = access.SelectAll<BaseDataObject>();
And again, this is to loop on them recursively:
static void Main(string[] args)
{
BaseDataAccess access =
new BaseDataAccess(@"D:\XmlFiles\StructureMap.xml",
"doesntMatter");
List<BaseDataObject> objects = access.SelectAll<BaseDataObject>();
for (int i = 0; i < objects.Count; i++)
PrintObject(objects[i]);
Console.ReadLine();
}
private static void PrintObject(BaseDataObject obj)
{
if (obj.Childs.Count > 0)
{
Console.WriteLine(obj.Name + " >");
for (int i = 0; i < obj.Childs.Count; i++)
PrintObject(obj.Childs[i]);
}
else
Console.WriteLine(obj.Name + " : " + obj.Value);
}
History
The code in the library is fully commented. This is version 1. I hope we can add more and more features in the future.