In This Topic
    Nodes, Attributes and Elements
    In This Topic

    Nodes

    Many applications require to hierarchically organize their documents or other internally maintained structures. In fact the hierarchical organization of structures is a core concept in the building of every type of scene. In this aspect each object in a hierarchy can be treated as a node of the scene tree. In the Nevron DOM the basic abstraction of node is represented by the INNode interface.

    In general there are two types of nodes:

    • Leaf ? a node without any child nodes
    • Branch - a node with one or many child nodes

    Common for all types of nodes is that you can obtain the immediate node parent as well as the root node (the topmost node in the hierarchy). For example:

    [Visual Basic]
    ' obtain the node parent in the scene
    Dim parent as INNode = node.ParentNode
    ' obtain the scene root
    Dim root as INNode = node.RootNode
    
    [C#]
    // obtain the node parent in the scene
    INNode parent = node.ParentNode;
    // obtain the scene root
    INNode root = node.RootNode;
    

    Branch nodes can also be in general classified as follows:

    • Branches with predefined children - these are branch nodes whose children are predefined for the purpose of the specific application. In Nevron DOM this type of branch nodes is represented by the INNodeContainer interface (derived from INNode ). For each node container you can execute the following code:
      [Visual Basic]
      ' get the container child nodes
      Dim children As NNodeList = container.Children(Nothing)
      ' get the child at some index
      Dim child As INNode = container.GetChildAt(0)
      ' get the container descendant nodes
      Dim descendants As NNodeList = container.Descendants(Nothing, -1)
      
      [C#]
      // get the container child nodes
      NNodeList children = container.Children(null);
      // get the child at some index
      INNode child = container.GetChildAt(0);
      // get the container descendant nodes
      NNodeList descendants = container.Descendants(null);
      
    • Branches with user defined children - these are branch nodes to which you can insert and remove children. In Nevron DOM this type of branch nodes is represented by the INNodeComposite interface. INNodeComposite (derived from INNodeContainer ). For each composite node you can execute the following code:
      [Visual Basic]
      ' add a child node
      composite.AddChild(node1)
      ' insert a child node
      composite.InsertChild(0, node2)
      ' remove a child node
      composite.RemoveChild(node1)
      ' remove a child at some index
      composite.RemoveChildAt(0)
      
      [C#]
      // add a child node
      composite.AddChild(node1);
      // insert a child node
      composite.InsertChild(0, node2);
      // remove a child node
      composite.RemoveChild(node1);
      // remove a child at some index
      composite.RemoveChildAt(0);
      

    It is also often required to enumerate the nodes, which reside in the sub tree of a particular node container. The Nevron DOM provides two types of node tree enumerators ? forward and reversed. They both support the following tree traversal orders:

    • Breadth First - visits the nodes by levels
    • Depth First Post Order - visits the children and then visits the parent
    • Depth First Pre Order - visits the parent and then visits the children
    [Visual Basic]
    ' forward enumeration
    Dim en As New NNodeTreeEnumerator(nodeContainer, Nothing, -1, TreeTraversalOrder.DepthFirstPreOrder)
    While en.MoveNext()
        Dim cur As INNode = en.Current
    End While
    
    ' reverse enumeration
    Dim ren As New NReverseNodeTreeEnumerator(nodeContainer, Nothing, -1, TreeTraversalOrder.DepthFirstPreOrder)
    While ren.MoveNext()
        Dim cur As INNode = ren.Current
    End While
    
    [C#]
    // forward enumeration 
    NNodeTreeEnumerator en = new NNodeTreeEnumerator(nodeContainer, null, -1, TreeTraversalOrder.DepthFirstPreOrder); 
    while (en.MoveNext())
    { 
        INNode cur = (INNode)en.Current;
    } 
    
    // reverse enumeration 
    NReverseNodeTreeEnumerator ren = new NReverseNodeTreeEnumerator(nodeContainer, null, -1, TreeTraversalOrder.DepthFirstPreOrder);
    while (ren.MoveNext())
    {
        INNode cur = (INNode)en.Current;
    }
    

    Attributes

    In the Nevron DOM, attributes the primary means with which you can attach additional, classified information to objects (not necessarily only to nodes or elements). The abstraction of an attribute is defined by the INAttribute interface a core implementation of which can be found in the NAttribute class.

    Objects declare the fact that they contain attributes by implementing the INAttributeContainer inferace. In the case when this interface is implemented by an attribute it is said that this attribute is a composite attribute.

    Each attribute has two names:

    • Local name - the local attribute name is provided to the attribute by the attribute container in which it resides. It can be obtained by the AttributeName property.
    • Full name ? the full attribute name is the concatenation of its parent attribute names (if any) and its local name divided with the '.' character. The full attribute name can be obtained from its FullAttributeName property.
    Attributes are designed to notify their first container, which implements the INAttributeObserver interface when a property or the state of the attribute has changed.

    Elements

    In the Nevron DOM, elements are the primary document building blocks. The abstraction of an element is defined by the INElement interface.

    Elements are nodes (the INElement interface derives from the INNode interface). This ensures that elements can be organized in hierarchical structures. A node container, which consists only of elements, must implement the INElementContainer interface (derived from INNodeContainer). Analogously a composite node, which can only contain elements, must implement the INElementComposite interface).

    Elements are identifiable. Each element can be identified by its Id or UniqueId (the INElement interface derives from the INIdentifiable and INUniquelyIdentifiable interface)). The Id of an element is unique only in the scope of the document in which the element resides. The UniqueId of an element is a GUID, which ensures that the element can be uniquely identified in the scope of several documents.

    By design elements are attribute containers and are notified when their attributes change (the INElement interface derives from the INAttributeContainer and INAttributeObserver interfaces).

    Elements can be cloned in two ways:

    • Deep Clone with the same Unique Id - this type of cloning is performed by the standard .NET Clone() method (the INElement interface derives from ICloneable).
    • Deep Clone with new Unique Id - this type of cloning is performed by the CloneWithNewUniqueId method. This method accepts a single parameter ? a map of unique ids, which is populated with the made unique id changes.
    In both types of cloning the id of the element cloning is by default set to -1, in order to indicate that the cloning does not yet reside in any document. Elements typically reference other elements by their unique id. Any unique ids, which an element stores in order to reference other elements are called foreign unique ids .

    By design the INElement interface provides the basic means to change the element references with the help of the ReplaceForeignUniqueIds methods.

    See Also

    INNode | INNodeContainer | INNodeComposite | INAttribute | INAttributeContainer | INAttributeObserver | INElement | INElementContainer | INElementComposite | NAttribute | NNodeTreeEnumerator | NReverseNodeTreeEnumerator