C# Elmax

Table of contents

Element

Element is the main class in the Elmax. Most activities takes place directly or indirectly with Element class. This section deals with the in and outs of the Element class.

Element Creation

Element can be created by calling Create and CreateNew method explicitly or by calling one of the mutators which will create the element node if it does not exists. Create does not create if the node with name is already exists. CreateNew will always create. Note that when you call CreateNew repeatedly, only the last element gets created. Let me show you a code example to explain this. In ther example below, In the first CreateNew call, elements aa, bb, and cc are created. In each subsequent call, only the element cc is created. Note: please pass in a valid non-null namespace URI argument if there is a namespace associated with the new element.

XmlDocument doc;
bool created = CreateAndInitDom(out doc);
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem1 = root["aa|bb|cc"].CreateNew(null);
    Element elem2 = root["aa|bb|cc"].CreateNew(null);
    Element elem3 = root["aa|bb|cc"].CreateNew(null);
}

This is the output XML.

<aa>
  <bb>
    <cc/>
    <cc/>
    <cc/>
  </bb>
</aa>

Element Deletion

Element is deleted through the Delete method.

XmlDocument doc;
bool created = CreateAndInitDom(out doc);
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
	elem.Delete();
}

Element Mutators

Element values are set through the mutators.

XmlDocument doc;
bool created = CreateAndInitDom(out doc);
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
    int dd = 2000000000;
    elem["dd"].SetInt(dd);
}

This is a list of mutators which the Element class supports.

public bool SetBool(bool val);

public bool SetSByte(sbyte val);

public bool SetShort(short val);

public bool SetLong(long val);

public bool SetUShort(ushort val);

public bool SetUInt(uint val);

public bool SetULong(ulong val);

public bool SetFloat(float val);

public bool SetDouble(double val);

public bool SetString(string val);

public bool SetGuid(Guid val, bool bRemoveBraces);

public bool SetDate(DateTime val);

public bool SetDateTime(DateTime val);

public bool SetFileContents(string filepath, bool bSaveFilename, bool bSaveFileLength);

public bool SetHex(uint val, bool bAddPrefix);


Element Accessors

Developer supplies a default value to the accessor, in case the value does not exists or it is invalid. The default value will be assigned back to the caller.

XmlDocument doc;
bool created = CreateAndInitDom(out doc);
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
    int dd = 2000000000;
    elem["dd"].SetInt(dd);

    int dd2 = elem["dd"].GetInt(10);
}

This is a list of accessors which the Element class supports.

public bool GetBool(bool defaultVal);

public sbyte GetSByte(sbyte defaultVal);

public short GetShort(short defaultVal);

public int GetInt(int defaultVal);

public long GetLong(long defaultVal);

public byte GetByte(byte defaultVal);

public ushort GetUShort(ushort defaultVal);

public uint GetUInt(uint defaultVal);

public ulong GetULong(ulong defaultVal);

public float GetFloat(float defaultVal);

public double GetDouble(double defaultVal);

public string GetString(string defaultVal);

public Guid GetGuid(Guid defaultVal);

public DateTime GetDate(DateTime defaultVal);

public DateTime GetDateTime(DateTime defaultVal);

public byte[] GetFileContents(out string filename, out int length);

public uint ReadHex(uint defaultVal);

Element Collection

Collection of the element children is done through the GetCollection method. There is a similar AsCollection method which get the siblings with the same name.

XmlDocument doc;
bool created = CreateAndInitDom(out doc);
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem1 = root["aa|bb|cc"].CreateNew(null);
    elem1.SetInt(11);
    Element elem2 = root["aa|bb|cc"].CreateNew(null);
    elem2.SetInt(22);
    Element elem3 = root["aa|bb|cc"].CreateNew(null);
    elem3.SetInt(33);

    List<Element> list = root["aa"]["bb"].GetCollection("cc");
}

Here is an example to call predicate version of GetCollection with lambda.

XmlDocument doc;
bool created = CreateAndInitDom(out doc);
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem1 = root["aa|bb|cc"].CreateNew(null);
    elem1.SetInt(11);
    Element elem2 = root["aa|bb|cc"].CreateNew(null);
    elem2.SetInt(22);
    Element elem3 = root["aa|bb|cc"].CreateNew(null);
    elem3.SetInt(33);

    List<Element> list = root["aa"]["bb"].GetCollection("cc", x => x.GetInt(0)< 33);
}

Root Element

RootElement is the helper class contributed by PJ Arends to eliminate the need to call SetDomDoc.

Root Element Load File

The RootElement constructor takes in a file path and loads the XML file into the DOM if exists. Else the document is a empty DOM. When the user calls SaveFile, he/she can either specifies a new path or the constructor path is used.

string path = "D:\\temp.xml";
RootElement root = new RootElement(path); // load the file if it exists

// Use RootElement like other elements
Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
elem["dd"].SetBool(true);

If user used an Element as root, the equivalent code is

XmlDocument doc = new XmlDocument();

string path = "D:\\temp.xml";

if(File.Exists())
{
    doc.LoadXml(path)
}

Element root = new Element();
root.SetDomDoc(doc);

// Use RootElement like other elements
Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
elem["dd"].SetBool(true);

Root Element Save File

File is saved through the SaveFile method.

string path = "D:\\temp.xml";
RootElement root = new RootElement(path); // load the file if it exists

// Use RootElement like other elements
Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
elem["dd"].SetBool(true);

root.SaveFile();

Attribute

Attribute Creation

Attribute can be created by calling Create method explicitly or by calling one of the mutators which will create the attribute node if it does not exists. Please note exception will be thrown if the element, on which the attribute is to be created, does not exists. Please use Element's Exists to check the element exists before calling the mutators. Calling the mutators is the recommended way to create attribute nodes. Below is an example code of calling the integer mutator to create the attribute implicitly.

XmlDocument doc;
bool created = CreateAndInitDom(out doc);
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
    int dd = 2000000000;
    Assert.IsTrue(elem.Exists);
	// attr attribute will be created automatically
    Attribute attr = elem.Attribute("Attr");
}

Attribute Deletion

Attribute node is deleted, using the Delete method on the Attribute class.

XmlDocument doc;
bool created = CreateAndInitDom(out doc);
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
    int dd = 2000000000;
    elem.Attribute("Attr").SetInt(dd);

    Elmax.Attribute attr = elem.Attribute("Attr");

    attr.Delete();
}

Attribute Mutators

We use mutators to change the value of the attribute.

XmlDocument doc;
bool created = CreateAndInitDom(out doc);
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
    int dd = 2000000000;
    Assert.IsTrue(elem.Exists);
	// attr attribute will be created automatically
    Attribute attr = elem.Attribute("Attr");
	attr.SetInt(dd);
}

This is a full list of mutators which Attribute class supports.

public bool SetBool(bool val);

public bool SetSByte(sbyte val);

public bool SetShort(short val);

public bool SetInt(int val);

public bool SetLong(long val);

public bool SetByte(byte val);

public bool SetUShort(ushort val);

public bool SetUInt(uint val);

public bool SetULong(ulong val);

public bool SetFloat(float val);

public bool SetDouble(double val);

public bool SetString(string val);

public bool SetGuid(Guid val, bool bRemoveBraces);

public bool SetDate(DateTime val);

public bool SetDateTime(DateTime val);

public bool SetHex(uint val, bool bAddPrefix);

Attribute Accessors

Developer would use accessors to retrieve the value of the attribute. If the value does not exist or it is invalid, the default value supplied to the accessor will be re-assigned to the caller. This is an example of calling the 32 bit integer accessor.

XmlDocument doc;
bool created = CreateAndInitDom(out doc);
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
    int dd = 2000000000;
    Assert.IsTrue(elem.Exists);
	// attr attribute will be created automatically
    Attribute attr = elem.Attribute("Attr");
	attr.SetInt(dd);
    int dd3 = attr.GetInt(10);
}

This is a full list of accessors which Attribute class supports.

public bool GetBool(bool defaultVal);

public sbyte GetSByte(sbyte defaultVal);

public short GetShort(short defaultVal);

public int GetInt(int defaultVal);

public long GetLong(long defaultVal);

public byte GetByte(byte defaultVal);

public ushort GetUShort(ushort defaultVal);

public uint GetUInt(uint defaultVal);

public ulong GetULong(ulong defaultVal);

public float GetFloat(float defaultVal);

public double GetDouble(double defaultVal);

public string GetString(string defaultVal);

public Guid GetGuid(Guid defaultVal);

public DateTime GetDate(DateTime defaultVal);

public DateTime GetDateTime(DateTime defaultVal);

private bool GetString(string defaultVal, out string val);

public uint ReadHex(uint defaultVal);

Attribute Collection

We can get a list of attributes which the element node currently holds, by calling the Element's GetAttributes method. This is an example of calling GetAttributes.

XmlDocument doc;
bool created = CreateAndInitDom(out doc);
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
    bool dd = true;
    int dd2 = 123;
    elem.Attribute("Attr1").SetBool(dd);
    elem.Attribute("Attr2").SetInt(dd2);
    elem.Attribute("Attr3").SetString("Hello");

    List<Elmax.Attribute> attrs = elem.GetAttributes();
}


CData Section

This section shows the methods to manipulate the CData section node.

CData Creation

CData section node can be added to the element through the AddCData method of the Element class. Below is an example of how to add a CData section.

XmlDocument doc;
bool created = CreateAndLoadXml(out doc, "example.xml");
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
    Assert.IsTrue(elem.Exists);
    System.String strCData = "<data>Where is my data?</data>";
    elem.AddCData(strCData);
}

CData Deletion

The CData section node can be deleted through the Delete method of the CData class. Element class provides a DeleteAllCData method to delete all the CData section under the element. Below is an example of how to delete a CData section.

XmlDocument doc;
bool created = CreateAndLoadXml(out doc, "example.xml");
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
    System.String comment = "Can you see me?";
    elem.AddComment(comment);

    Comment comment = elem.GetCommentCollection()[0];

    comment.Delete();
}

CData Mutators

The contents of CData section node can be changed through the Update method of the CData class. Below is an example of how to update a CData section contents.

XmlDocument doc;
bool created = CreateAndLoadXml(out doc, "example.xml");
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
    System.String strCData = "<data>Where is my data?</data>";
    elem.AddCData(strCData);

    CData cdata = elem.GetCDataCollection()[0];

    System.String update = "<data>Where is my world?</data>";
    cdata.Update(update);
}


CData Accessors

The contents of the CData section can be retrieved through the GetContent method which returns a string. Below is the example of getting the CData contents.

XmlDocument doc;
bool created = CreateAndLoadXml(out doc, "example.xml");
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
    Assert.IsTrue(elem.Exists);
    System.String strCData = "<data>Where is my data?</data>";
    elem.AddCData(strCData);

    CData cdata = elem.GetCDataCollection()[0];

    System.String s1 = strCData;
    System.String s2 = cdata.GetContent();
}

CData Collection

CData section collection can be retrieved through the GetCDataCollection method of the Element class. Below is an example on how to call GetCDataCollection method.

XmlDocument doc;
bool created = CreateAndLoadXml(out doc, "example.xml");
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);

    List<CData> list = elem.GetCDataCollection();
}

Comment Creation

Comment objects are created through the AddComment method of the Element class. Below is example on how to add a comment node to the element.

XmlDocument doc;
bool created = CreateAndLoadXml(out doc, "example.xml");
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
    Assert.IsTrue(elem.Exists);
    System.String comment = "Can you see me?";
    elem.AddComment(comment);
}

Comment Deletion

Comment node is deleted through the Delete method in the Comment class. To delete all comments in a element, call DeleteAllComment method of the Element class. This is the way to call Delete method.

XmlDocument doc;
bool created = CreateAndLoadXml(out doc, "example.xml");
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
    Assert.IsTrue(elem.Exists);
    System.String comment = "Can you see me?";
    elem.AddComment(comment);

    Comment comment = elem.GetCommentCollection()[0];

    comment.Delete();
}



Comment Mutators

Comment node are changed through the Update method on the Comment class. Below is a example on how to update the comment node.

XmlDocument doc;
bool created = CreateAndLoadXml(out doc, "example.xml");
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);
    Assert.IsTrue(elem.Exists);
    System.String comment = "Can you see me?";
    elem.AddComment(comment);

    Comment comment = elem.GetCommentCollection()[0];

    System.String update = "Cannot see anything!";
    comment.Update(update);
}

Comment Accessors

The contents of the comment can be retrieved through the GetContent of the Comment class. Below is the sample code on how to call GetContent.

XmlDocument doc;
bool created = CreateAndLoadXml(out doc, "example.xml");
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);

    Comment comment = elem.GetCommentCollection()[0];

    System.String s2 = comment.GetContent();
}

Get Comment Collection

As the reader has seen earlier, he/she can get a collection from element through the GetCommentCollection method. Below is an example on how to use this method.

XmlDocument doc;
bool created = CreateAndLoadXml(out doc, "example.xml");
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem = root["aa"]["bb"]["cc"].CreateNew(null);

    List<Comment> list = elem.GetCommentCollection();
}

HyperElement

One to One Join

HyperElement is a class which can link one element to another element elsewhere. listElem1 and listElem2 are a list of elements to be link up. attrName1 and attrName2 are attributes whose exact same values will be linked up. In the case of more than 1 element whose attribute has the same value, it is a case of 1st found, 1st linked. If attribute name is empty, the element value will be used instead of the attribute value. CaseSensitive indicates if the attribute value comparison is case sensitive.

public static List< KeyValuePair<Elmax.Element, Elmax.Element> >
    JoinOneToOne(
        List<Elmax.Element> listElem1,
        string attrName1,
        List<Elmax.Element> listElem2,
        string attrName2,
        bool caseSensitive);

Below is an example on how the JoinOneToOne is used.

XmlDocument doc;
bool created = CreateAndLoadXml(out doc, "example.xml");
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem1 = root["aa|bb|cc"];
    Element elem4 = root["dd|ee"];

    List< KeyValuePair<Elmax.Element, Elmax.Element> > list =
        HyperElement.JoinOneToOne(elem1.AsCollection(), "", elem4.AsCollection(), "SomeValue", false);
}

There is also a predicate version of JoinOneToOne where lambda, delegate and anonymous delegate can be used as predicate for the comparison.

public static List<KeyValuePair<Elmax.Element, Elmax.Element>>
    JoinOneToOne(
        List<Elmax.Element> listElem1,
        List<Elmax.Element> listElem2,
        DoubleElementPrediate pred);

Below is sample code of how the prediate version of JoinOneToOne is used with a lambda.

XmlDocument doc;
bool created = CreateAndLoadXml(out doc, "example.xml");
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem1 = root["aa|bb|cc"];

    Element elem4 = root["dd|ee"];

    List<KeyValuePair<Elmax.Element, Elmax.Element>> list =
        HyperElement.JoinOneToOne(elem1.AsCollection(), elem4.AsCollection(), (x, y)=> x.GetInt(0)==y.Attribute("SomeValue").GetInt(1));
}

One to Many Join

HyperElement is a class which can link one element to a list of elements whose attribute values matched. listElem1 and listElem2 are a list of elements to be link up. attrName1 and attrName2 are attributes whose exact same values will be linked up. In the case of more than 1 element whose attribute has the same value, it is a case of 1st found, 1st linked. If attribute name is empty, the element value will be used instead of the attribute value. CaseSensitive indicates if the attribute value comparison is case sensitive.

public static List<KeyValuePair<Elmax.Element, List<Elmax.Element>>>
    JoinOneToMany(
        List<Elmax.Element> listElem1,
        string attrName1,
        List<Elmax.Element> listElem2,
        string attrName2,
        bool caseSensitive);

Below is an example on how the JoinOneToMany is used.

XmlDocument doc;
bool created = CreateAndLoadXml(out doc, "example.xml");
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem1 = root["aa|bb|cc"];

    Element elem4 = root["dd|ee"];

    List<KeyValuePair<Elmax.Element, List<Elmax.Element> > > list =
        HyperElement.JoinOneToMany(elem1.AsCollection(), "", elem4.AsCollection(), "SomeValue", false);
}

public static List<KeyValuePair<Elmax.Element, List<Elmax.Element>>>
    JoinOneToMany(
        List<Elmax.Element> listElem1,
        List<Elmax.Element> listElem2,
        DoubleElementPrediate pred);

Below is a sample code of how the prediate version of JoinOneToMany is used.

XmlDocument doc;
bool created = CreateAndLoadXml(out doc, "example.xml");
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);

    Element elem1 = root["aa|bb|cc"];

    Element elem4 = root["dd|ee"];

    List<KeyValuePair<Elmax.Element, List<Elmax.Element>>> list =
        HyperElement.JoinOneToMany(
            elem1.AsCollection(), 
            elem4.AsCollection(), 
            (x, y) => x.GetInt(0) == y.Attribute("SomeValue").GetInt(1));
}

XPath

Document level

Document level XPath is done, using the Document class.

XmlDocument doc;
bool created = CreateAndLoadXml(out doc, "example.xml");
Document elmaxDoc = new Document(doc);
List<Element> nodes = elmaxDoc.GetElementsByTagName("dd");

Below is the list of XPath methods in Document class.

public List<Elmax.Element> GetElementsByTagName(string tagName);
public List<Elmax.Element> GetElementsByTagName(string tagName, string namespaceURI);
public Elmax.Element GetElementById(string id);
public List<Elmax.Element> SelectNodes(string xpath);
public Elmax.Element SelectSingleNode(string xpath);

Note: C# has more XPath methds than the C++ equivalent, simply because the .NET XmlDocument provides more of these mthods for Elmax Document class to wrap.

Element level

Element level XPath is done, using the Element class.

XmlDocument doc;
bool created = CreateAndLoadXml(out doc, "example.xml");
if (created)
{
    Element root = new Element();
    root.SetDomDoc(doc);
    Element elem = root["aa/bb/cc"].CreateNew(null);

    Element singleNode = root.SelectSingleNode("//dd");
}

Below is the list of XPath methods in Element class.

public Element SelectSingleNode(string xpath);
public List<Element> SelectNodes(string xpath);

Helper Methods

The helper methods used in this documentation to load and save XML are listed in this section.

Create Empty XML Document

You can use the below methods to create a empty UTF-8 DOM document.

bool CreateAndInitDom(out XmlDocument doc)
{
    doc = new XmlDocument();
    if (doc != null)
    {
        XmlProcessingInstruction pi = doc.CreateProcessingInstruction("xml", " version='1.0' encoding='UTF-8'");
        doc.AppendChild(pi);
    }
    else
        return false;

    return true;
}

Load XML Document

You can use the below methods to load the XML from file.

bool CreateAndLoadXml(out XmlDocument doc, System.String strFilename)
{
    doc = new XmlDocument();
    try
    {
        doc.Load(strFilename);
    }
    catch (System.Exception)
    {
        return false;
    }
    return true;
}

Save XML Document

You can use the below methods to save the XML.

bool SaveXml(XmlDocument doc, System.String strFilename)
{
    System.String path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
    path = Path.Combine(path, strFilename);
    doc.Save(path);
    FileInfo fi = new FileInfo(path);

    return fi.Exists;
}

Save XML Document with indentation

You can use the PrettySave method of the Document class to save the XML with the proper indentation and newlines.

bool SaveXml(XmlDocument doc, System.String strFilename)
{
    System.String path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
    path = Path.Combine(path, strFilename);
    Document xdoc = new Document(doc);
    xdoc.PrettySave(path);
    FileInfo fi = new FileInfo(path);

    return fi.Exists;
}

Last edited Apr 18, 2012 at 9:24 AM by shaovoon, version 5

Comments

No comments yet.