DOM guide: Working with elements: Difference between revisions
(13 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
Two classes provide methods for working with elements after you have loaded a [[COLLADA instance document]] into your application: | Two classes provide methods for working with elements after you have loaded a [[COLLADA instance document]] into your application: | ||
* | *<code>daeDatabase</code> provides access to elements within a document. | ||
* | *<code>daeElement</code> is the base class for all [[COLLADA Object Model]] classes. This class uses the [[Reflective Object System]] (ROS) to provide considerable functionality without the need to use the generated subclass. | ||
==Querying Database Elements== | ==Querying Database Elements== | ||
The current version of the [[COLLADA DOM]] provides two methods to query the database to get | The current version of the [[COLLADA DOM]] provides two methods to query the database to get | ||
information about specific elements: | information about specific elements: | ||
* | *<code>daeDatabase::getElementCount</code> | ||
* | *<code>daeDatabase::getElement</code> | ||
:'''''Note:''' domConstants.h provides constants for the element tag names (COLLADA_ELEMENT_*) and the element types (COLLADA_TYPE_*). When querying the database for elements based on type, always use the COLLADA_TYPE_* constant.'' | :'''''Note:''' <code>domConstants.h</code> provides constants for the element tag names (<code>COLLADA_ELEMENT_*</code>) and the element types (<code>COLLADA_TYPE_*</code>). When querying the database for elements based on type, always use the <code>COLLADA_TYPE_*</code> constant.'' | ||
===getElementCount=== | ===getElementCount=== | ||
<code>getElementCount</code> returns the number of elements for a particular query. For example, the following code asks how many <image> elements are in the database: | |||
imageCount = collada_dom->getDatabase()->getElementCount(NULL, COLLADA_TYPE_IMAGE, NULL); | imageCount = collada_dom->getDatabase()->getElementCount(NULL, COLLADA_TYPE_IMAGE, NULL); | ||
The additional parameters to | The additional parameters to <code>getElementCount</code> make the request more specific. The first parameter represents the ID of the element. The third parameter represents the name of the document, and might be used if you have loaded elements from multiple instance documents. | ||
===getElement=== | ===getElement=== | ||
<code>getElement</code> requests that the database return a specific element. For example, the | |||
following code returns an | following code returns an <image> element with an index that matches the value in el_number. | ||
domImage *thisImage; | domImage *thisImage; | ||
daeInt error = collada_dom->getDatabase()->getElement((daeElement**)&thisImage, el_number, NULL, COLLADA_TYPE_IMAGE, NULL); | daeInt error = collada_dom->getDatabase()->getElement((daeElement**)&thisImage, el_number, NULL, COLLADA_TYPE_IMAGE, NULL); | ||
Line 26: | Line 26: | ||
===Technique for querying elements=== | ===Technique for querying elements=== | ||
Typically, | Typically, <code>getElementCount</code> and <code>getElement</code> are used as a pair, first getting the number of elements that match a particular ID, type, or document query, and then iterating through those by using the <code>getElement</code> method. For example, if you want to take an action on all of the images in the database, you could do the following: | ||
imageCount = collada_dom->getDatabase()->getElementCount(NULL, COLLADA_TYPE_IMAGE, NULL); | imageCount = collada_dom->getDatabase()->getElementCount(NULL, COLLADA_TYPE_IMAGE, NULL); | ||
Line 43: | Line 43: | ||
} | } | ||
The index passed to | The index passed to <code>getElement</code> is not directly associated with the element within the database. The index relates to the query itself. The queries used for <code>getElementCount</code> and <code>getElement</code> must match in order for the index to be valid when passed to the <code>getElement</code> method. | ||
==Determining an Element's Type== | ==Determining an Element's Type== | ||
There are three approaches to determining the type of a | There are three approaches to determining the type of a <code>daeElement</code>: | ||
* Using the | * Using the <code>daeElement::getElementType</code> method, which returns an enumerated value respresenting the element's type. The values returned by this function are in the <code>dom/domTypes.h</code> header. This is the easiest approach. | ||
*Using the | *Using the <code>daeElement::getTypeName</code> method, which returns a <code>daeString</code> containing the type name. To determine the type, compare this string with the matching <code>COLLADA_TYPE_*</code> constant defined in <code>dom/domConstants.h</code>. | ||
*By comparing the | *By comparing the <code>daeElement::_meta</code> variable. The <code>_meta</code> is a pointer to a <code>daeMetaElement</code>, which is the class that contains all the ROS information for an element type. By doing a pointer comparison on <code>daeElement::getMeta</code> and the generated class's static <code>dom*::_Meta</code>, it is possible to find the element type. This is the approach that the <code>daeSafeCast</code> method uses to ensure type safety. (See also: [[DOM meta system]].) | ||
'''''NOTE:''' The | '''''NOTE:''' The <code>daeSafeCast</code> and <code>daeElement::getElementType</code> approaches are newer additions to the COLLADA DOM. When looking at older source code using the DOM, expect to see the older methods used frequently for type checking.'' | ||
==Determining an Element's Name== | ==Determining an Element's Name== | ||
Use the | Use the <code>daeElement:getElementName</code> method to retrieve the name of an element. The element name is the XML tag that would be present in a COLLADA instance document. | ||
For the majority of elements in the COLLADA DOM, | For the majority of elements in the COLLADA DOM, <code>getElementName</code> returns NULL, indicating that the element's name is the same as its type name, available from <code>daeElement::getTypeName</code>. | ||
==Accessing Element Data== | ==Accessing Element Data== | ||
The | The easiest way to access element data is to cast the <code>daeElement</code> to its strongly typed subclass. However, at times, it might not be possible to do the cast or it might be more convenient not to cast. The <code>daeElement</code> class provides methods to access and manipulate data directly for such situations. | ||
===Navigating the Object Model=== | ===Navigating the Object Model=== | ||
<code>daeElement</code> provides the following methods for accessing various information about an element: | |||
* | *<code>getDocument</code> provides access to the [[COLLADA document]] that the element belongs to. | ||
* | *<code>getDocumentURI</code> is a helper method if you need only the document's name. | ||
* | *<code>getParentElement</code> returns the parent element, which allows you to traverse up the tree to the root. If this method returns NULL, the element is the root of the tree. If the root element belongs to a document (<code>getDocument</code> or <code>getDocumentURI</code> are non-NULL) then it is safe to assume that the element is a <code>domCOLLADA</code> element, which is an element that is the root of a COLLADA document. | ||
* | *<code>getChildren</code> populates an array with the children of an element. This allows you to iterate over all the children of an element and traverse down the element hierarchy. This array is ordered the same as it would be if the element were written to a [[COLLADA instance document]]. This array is the same as the <code>_contents</code> array, if an element's dom* subclass has a <code>_contents</code> array. | ||
===Accessing Attributes=== | ===Accessing Attributes=== | ||
The | The <code>daeElement</code> class provides many functions for accessing the attributes that an element may have: | ||
* | *<code>setAttribute</code> takes both the attribute name and the new value as string arguments. The COLLADA DOM converts the value from a string to the data type of the attribute. This method returns false if the element does not have an attribute with the specified name. | ||
* | *<code>hasAttribute</code> queries the existence of an attribute. | ||
* | *<code>isAttributeSet</code> returns true if the attribute exists and has been set. The attribute can be set when loading the document or programmatically. Attributes with default values are always considered set. | ||
* | *<code>getAttributeValue</code> returns a byte pointer to the memory used to store the specified attribute. The client application is responsible for type casting this pointer to the appropriate type before using it. One common mistake occurs when dealing with string attributes. Remember that this function returns a pointer to the data and that <code>daeString</code> is a pointer itself, therefore this function returns a pointer to a pointer for string attributes. | ||
===Accessing the Value=== | ===Accessing the Value=== | ||
Line 86: | Line 86: | ||
==Adding and Removing Elements== | ==Adding and Removing Elements== | ||
The | The <code>daeElement</code> class provides methods for adding elements to, and removing them from, the Object Model. Using these methods ensures that the element bookkeeping information maintained by the COLLADA DOM is appropriately updated. For example, many DOM classes contain a <code>_contents</code> array, which keeps the correct order of all the child elements of that DOM class so they can be written in the valid order. The DOM maintains the <code>_contents</code> array automatically when you use these methods to create and delete child elements. | ||
'''''Note.''' We strongly advise againt manually updating the | '''''Note.''' We strongly advise againt manually updating the <code>_contents</code> array as it is very error-prone.'' | ||
===Adding Elements=== | ===Adding Elements=== | ||
The method | The method <code>daeElement::createAndPlace</code> creates a new element as a child of the current element. It places the new element in the appropriate field of its parent element based on the <code>className</code> parameter provided in the method invocation. | ||
The following example demonstrates how to add a new light to an existing library of lights: | The following example demonstrates how to add a new light to an existing library of lights: | ||
Line 97: | Line 97: | ||
domLight *newLight = daeSafeCast<domLight>(myLib->createAndPlace(COLLADA_ELEMENT_LIGHT)); | domLight *newLight = daeSafeCast<domLight>(myLib->createAndPlace(COLLADA_ELEMENT_LIGHT)); | ||
// Now you can add data to the new light. | // Now you can add data to the new light. | ||
:'''''Note:''' The <code>daeElement::create*</code> methods work with element tag names, not element types. When using the string constants provided in <code>domConstants.h</code>, use the <code>COLLADA_ELEMENT_*</code> value and not the <code>COLLADA_TYPE_*</code>. This is in contrast to working with the database, which uses element types.'' | |||
===Removing Elements=== | ===Removing Elements=== | ||
To remove a child element from its parent element, you can either of the following methods; the results are identical, but one might better suit your coding style: | To remove a child element from its parent element, you can use either of the following methods; the results are identical, but one might better suit your coding style: | ||
* | * <code>daeElement::removeChildElement</code> | ||
* | * <code>daeElement::removeFromParent</code>, which is a static method that finds the parent object automatically. | ||
The following example demonstrates one way to remove a light from a library of lights: | The following example demonstrates one way to remove a light from a library of lights: | ||
daeElement* lightParent = myLight-> | daeElement* lightParent = myLight->getParentElement(); | ||
// Remove the light | // Remove the light | ||
daeBool removed = lightParent->removeChildElement(myLight); | daeBool removed = lightParent->removeChildElement(myLight); | ||
Line 113: | Line 115: | ||
==Moving Elements== | ==Moving Elements== | ||
To move an element from one parent to another, use | To move an element from one parent to another, use <code>daeElement::placeElement</code>. <code>placeElement</code> handles all the "bookkeeping" for you. The element passed to <code>placeElement</code> is removed from its old location and inserted as a child to the element <code>placeElement</code> was called on. If the new parent belongs to a different document, <code>placeElement</code> updates all the document references and the runtime database. | ||
<code>placeElement</code> automatically inserts the new child in a valid location within the parent's content model. There may be many valid locations for the new child, but <code>placeElement</code> inserts the child in the first one available. To insert the new child at a specific location, use the <code>placeElementAt</code>, <code>placeElementBefore</code>, or <code>placeElementAfter</code> methods. | |||
==Copying Elements== | ==Copying Elements== | ||
To copy a DOM element, rather than using the assignment operator, use the | To copy a DOM element, rather than using the assignment operator, use the <code>daeElement::clone</code> method, which provides a deep copy operation. After the element is cloned, you need to resolve any URIs that have been copied, as <code>clone</code> does not do that automatically. | ||
The DOM type <code>daeString</code>, used in many objects derived from the <code>daeElement</code> class, is a C-style string and not a C++ string class. If you use the assignment operator to copy a <code>daeString</code>, you can end up with a dangling pointer if the original string is deleted. | |||
{{DOM | {{DOM navigation}} | ||
[[Category:DOM | [[Category:COLLADA DOM|Elements]] |
Latest revision as of 18:02, 26 September 2011
Two classes provide methods for working with elements after you have loaded a COLLADA instance document into your application:
daeDatabase
provides access to elements within a document.daeElement
is the base class for all COLLADA Object Model classes. This class uses the Reflective Object System (ROS) to provide considerable functionality without the need to use the generated subclass.
Querying Database Elements
The current version of the COLLADA DOM provides two methods to query the database to get information about specific elements:
daeDatabase::getElementCount
daeDatabase::getElement
- Note:
domConstants.h
provides constants for the element tag names (COLLADA_ELEMENT_*
) and the element types (COLLADA_TYPE_*
). When querying the database for elements based on type, always use theCOLLADA_TYPE_*
constant.
getElementCount
getElementCount
returns the number of elements for a particular query. For example, the following code asks how many <image> elements are in the database:
imageCount = collada_dom->getDatabase()->getElementCount(NULL, COLLADA_TYPE_IMAGE, NULL);
The additional parameters to getElementCount
make the request more specific. The first parameter represents the ID of the element. The third parameter represents the name of the document, and might be used if you have loaded elements from multiple instance documents.
getElement
getElement
requests that the database return a specific element. For example, the
following code returns an <image> element with an index that matches the value in el_number.
domImage *thisImage; daeInt error = collada_dom->getDatabase()->getElement((daeElement**)&thisImage, el_number, NULL, COLLADA_TYPE_IMAGE, NULL);
The element itself is returned in the first parameter. The third parameter restricts the query to a specific element by ID, and the fifth parameter restricts the search to a specific document.
Technique for querying elements
Typically, getElementCount
and getElement
are used as a pair, first getting the number of elements that match a particular ID, type, or document query, and then iterating through those by using the getElement
method. For example, if you want to take an action on all of the images in the database, you could do the following:
imageCount = collada_dom->getDatabase()->getElementCount(NULL, COLLADA_TYPE_IMAGE, NULL); for (unsigned int i=0; i<imageCount; i++) { error = collada_dom->getDatabase()->getElement((daeElement**)&thisImage, i, NULL, COLLADA_TYPE_IMAGE, NULL); /* take action on this image */ }
As another example, to take action on all images with the ID “landImage”, you could do the following:
imageCount = collada_dom->getDatabase()->getElementCount("landImage", COLLADA_TYPE_IMAGE, NULL); for (unsigned int i=0; i<imageCount; i++) { error = collada_dom->getDatabase()->getElement((daeElement**)&thisImage, i, "landImage", COLLADA_TYPE_IMAGE, NULL); /* take action on this land image */ }
The index passed to getElement
is not directly associated with the element within the database. The index relates to the query itself. The queries used for getElementCount
and getElement
must match in order for the index to be valid when passed to the getElement
method.
Determining an Element's Type
There are three approaches to determining the type of a daeElement
:
- Using the
daeElement::getElementType
method, which returns an enumerated value respresenting the element's type. The values returned by this function are in thedom/domTypes.h
header. This is the easiest approach.
- Using the
daeElement::getTypeName
method, which returns adaeString
containing the type name. To determine the type, compare this string with the matchingCOLLADA_TYPE_*
constant defined indom/domConstants.h
.
- By comparing the
daeElement::_meta
variable. The_meta
is a pointer to adaeMetaElement
, which is the class that contains all the ROS information for an element type. By doing a pointer comparison ondaeElement::getMeta
and the generated class's staticdom*::_Meta
, it is possible to find the element type. This is the approach that thedaeSafeCast
method uses to ensure type safety. (See also: DOM meta system.)
NOTE: The daeSafeCast
and daeElement::getElementType
approaches are newer additions to the COLLADA DOM. When looking at older source code using the DOM, expect to see the older methods used frequently for type checking.
Determining an Element's Name
Use the daeElement:getElementName
method to retrieve the name of an element. The element name is the XML tag that would be present in a COLLADA instance document.
For the majority of elements in the COLLADA DOM, getElementName
returns NULL, indicating that the element's name is the same as its type name, available from daeElement::getTypeName
.
Accessing Element Data
The easiest way to access element data is to cast the daeElement
to its strongly typed subclass. However, at times, it might not be possible to do the cast or it might be more convenient not to cast. The daeElement
class provides methods to access and manipulate data directly for such situations.
daeElement
provides the following methods for accessing various information about an element:
getDocument
provides access to the COLLADA document that the element belongs to.
getDocumentURI
is a helper method if you need only the document's name.
getParentElement
returns the parent element, which allows you to traverse up the tree to the root. If this method returns NULL, the element is the root of the tree. If the root element belongs to a document (getDocument
orgetDocumentURI
are non-NULL) then it is safe to assume that the element is adomCOLLADA
element, which is an element that is the root of a COLLADA document.
getChildren
populates an array with the children of an element. This allows you to iterate over all the children of an element and traverse down the element hierarchy. This array is ordered the same as it would be if the element were written to a COLLADA instance document. This array is the same as the_contents
array, if an element's dom* subclass has a_contents
array.
Accessing Attributes
The daeElement
class provides many functions for accessing the attributes that an element may have:
setAttribute
takes both the attribute name and the new value as string arguments. The COLLADA DOM converts the value from a string to the data type of the attribute. This method returns false if the element does not have an attribute with the specified name.hasAttribute
queries the existence of an attribute.isAttributeSet
returns true if the attribute exists and has been set. The attribute can be set when loading the document or programmatically. Attributes with default values are always considered set.getAttributeValue
returns a byte pointer to the memory used to store the specified attribute. The client application is responsible for type casting this pointer to the appropriate type before using it. One common mistake occurs when dealing with string attributes. Remember that this function returns a pointer to the data and thatdaeString
is a pointer itself, therefore this function returns a pointer to a pointer for string attributes.
Accessing the Value
- The daeElement::hasValue method is used to query if an element has a value.
- The daeElement::getValuePointer method works the same as daeElement::getAttributeValue except that it returns a pointer to the value field.
Adding and Removing Elements
The daeElement
class provides methods for adding elements to, and removing them from, the Object Model. Using these methods ensures that the element bookkeeping information maintained by the COLLADA DOM is appropriately updated. For example, many DOM classes contain a _contents
array, which keeps the correct order of all the child elements of that DOM class so they can be written in the valid order. The DOM maintains the _contents
array automatically when you use these methods to create and delete child elements.
Note. We strongly advise againt manually updating the _contents
array as it is very error-prone.
Adding Elements
The method daeElement::createAndPlace
creates a new element as a child of the current element. It places the new element in the appropriate field of its parent element based on the className
parameter provided in the method invocation.
The following example demonstrates how to add a new light to an existing library of lights:
// Add a new light to the library domLight *newLight = daeSafeCast<domLight>(myLib->createAndPlace(COLLADA_ELEMENT_LIGHT)); // Now you can add data to the new light.
- Note: The
daeElement::create*
methods work with element tag names, not element types. When using the string constants provided indomConstants.h
, use theCOLLADA_ELEMENT_*
value and not theCOLLADA_TYPE_*
. This is in contrast to working with the database, which uses element types.
Removing Elements
To remove a child element from its parent element, you can use either of the following methods; the results are identical, but one might better suit your coding style:
daeElement::removeChildElement
daeElement::removeFromParent
, which is a static method that finds the parent object automatically.
The following example demonstrates one way to remove a light from a library of lights:
daeElement* lightParent = myLight->getParentElement(); // Remove the light daeBool removed = lightParent->removeChildElement(myLight);
Here is the other method:
// Remove the light from its parent daeBool removed = daeElement::removeFromParent(myLight);
Moving Elements
To move an element from one parent to another, use daeElement::placeElement
. placeElement
handles all the "bookkeeping" for you. The element passed to placeElement
is removed from its old location and inserted as a child to the element placeElement
was called on. If the new parent belongs to a different document, placeElement
updates all the document references and the runtime database.
placeElement
automatically inserts the new child in a valid location within the parent's content model. There may be many valid locations for the new child, but placeElement
inserts the child in the first one available. To insert the new child at a specific location, use the placeElementAt
, placeElementBefore
, or placeElementAfter
methods.
Copying Elements
To copy a DOM element, rather than using the assignment operator, use the daeElement::clone
method, which provides a deep copy operation. After the element is cloned, you need to resolve any URIs that have been copied, as clone
does not do that automatically.
The DOM type daeString
, used in many objects derived from the daeElement
class, is a C-style string and not a C++ string class. If you use the assignment operator to copy a daeString
, you can end up with a dangling pointer if the original string is deleted.
COLLADA DOM - Version 2.4 Historical Reference |
---|
List of main articles under the DOM portal. |
User Guide chapters: • Intro • Architecture • Setting up • Working with documents • Creating docs • Importing docs • Representing elements • Working with elements • Resolving URIs • Resolving SIDs • Using custom COLLADA data • Integration templates • Error handling Systems: • URI resolver • Meta • Load/save flow • Runtime database • Memory • StringRef • Code generator |