Difference between revisions of "DOM guide: Importing documents"

From COLLADA Public Wiki
Jump to navigation Jump to search
Line 64: Line 64:
  
 
==Reading data from elements==
 
==Reading data from elements==
Any individual xml element has three types of data you might need: the element name, the element's attributes, and the element's character data. The DOM provides easy access to all of this data via the daeElement interface.
+
Any individual xml element has four types of data you might need: the element name, the element's attributes, the element's character data, and the element's child elements. The DOM provides easy access to all of this data via the daeElement interface.
  
 
===Element name===
 
===Element name===
Line 93: Line 93:
 
  cout << "attr " << i << " value: " << root->getAttribute(i) << endl;
 
  cout << "attr " << i << " value: " << root->getAttribute(i) << endl;
 
  }
 
  }
 +
 +
===Character data===
 +
You can retrieve an element's character data with the daeElement::getCharData method.
 +
 +
std::string getCharData();
 +
 +
For example, let's say you have an <asset> element and you want to tell if the <up_axis> setting is Z_UP. You could do that as follows.
 +
 +
daeElement* upAxis = asset->getDescendant("up_axis");
 +
if (upAxis && upAxis->getCharData() == "Z_UP")
 +
    // We have a match!
 +
 +
===Child elements===
 +
If you know the name of the child element you want, you can access it with daeElement::getChild.
 +
 +
daeElement* getChild(daeString eltName);
 +
 +
This will return null if the element with the given name doesn't exist. You might use this function to test for the existence of a particular child element.
 +
 +
if (root->getChild("asset") == NULL)
 +
    cout << "Missing <asset> element!\n"
 +
 +
If you don't have a specific element in mind you can get a list of all the child elements instead with the daeElement::getChildren method.
 +
 +
daeTArray< daeSmartRef<daeElement> > getChildren();
 +
 +
It returns an array of smart pointers to daeElement objects, which you can simply treat like ordinary daeElement pointers. You can use daeElement::getChildren to print a list of all the child elements of root like this.
 +
 +
daeTArray<daeElementRef> children = root->getChildren();
 +
for (size_t i = 0; i < children.getCount(); i++)
 +
cout << "child " << i << " name: " << children[i]->getElementName() << endl;
 +
 +
daeElementRef is just a typedef for daeSmartRef<daeElement> that's made available to DOM clients to keep code simpler.

Revision as of 23:29, 9 April 2008

Be sure to read the section on creating documents first. It covers some important topics relevant to this section.

A simple example

Let's begin with a simple example of reading some information from a Collada document. We'll open the document and print the ID of the first <node> we find.

DAE dae;
daeElement* root = dae.open("simpleImport.dae");
if (!root) {
    cout << "Document import failed.\n";
    return 0;
}

We create the DAE object then call DAE::open to open a file called "simpleImport.dae". If there is no file of that name in the current directory, or the file failed to open for some other reason, then the DAE::open method will return null. We check for that and print an error message if opening the document failed.

daeElement* node = root->getDescendant("node");
if (!node)
    cout << "No nodes found\n";
else
    cout << "node id: " << node->getAttribute("id") << endl;

Here we use the daeElement::getDescendant method to do a breadth-first search through the xml element tree for an element with the given name. This method will return null if it couldn't find an element with a matching name, which we check for. If it did find a matching element we use the daeElement::getAttribute method to print the value of the 'id' attribute.

The complete code.

#include <iostream>
#include <dae.h>
#include <dom/domCOLLADA.h>
using namespace std;

int main() {
	DAE dae;
	daeElement* root = dae.open("simpleImport.dae");
	if (!root) {
		cout << "Document import failed.\n";
		return 0;
	}

	daeElement* node = root->getDescendant("node");
	if (!node)
		cout << "No nodes found\n";
	else
		cout << "node id: " << node->getAttribute("id") << endl;

	return 0;
}

The simpleImport.dae document.

<?xml version="1.0" encoding="UTF-8"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
	<asset>
		<contributor/>
		<created>2008-04-08T13:07:52-08:00</created>
		<modified>2008-04-08T13:07:52-08:00</modified>
	</asset>
  <library_nodes>
    <node id="hello"/>
  </library_nodes>
</COLLADA>

And the results of running the program.

node id: hello

Reading data from elements

Any individual xml element has four types of data you might need: the element name, the element's attributes, the element's character data, and the element's child elements. The DOM provides easy access to all of this data via the daeElement interface.

Element name

Use the daeElement::getElementName method to get an element's name.

daeString getElementName() const; // Function signature
cout << elt->getElementName() << endl; // Example: print an element's name

Element attributes

To get the value of an attribute given the attribute's name, use the daeElement::getAttribute method.

std::string getAttribute(daeString name);

We've already seen an example of daeElement::getAttribute usage in the simple import example.

cout << "node id: " << node->getAttribute("id") << endl;

If you don't know what attributes an element has, you can iterate over its attribute list using the following methods of daeElement.

size_t getAttributeCount();
std::string getAttributeName(size_t i);
std::string getAttribute(size_t i);

This code snippet prints all the attribute names and values of the root element.

for (size_t i = 0; i < root->getAttributeCount(); i++) {
	cout << "attr " << i << " name: " << root->getAttributeName(i) << endl;
	cout << "attr " << i << " value: " << root->getAttribute(i) << endl;
}

Character data

You can retrieve an element's character data with the daeElement::getCharData method.

std::string getCharData();

For example, let's say you have an <asset> element and you want to tell if the <up_axis> setting is Z_UP. You could do that as follows.

daeElement* upAxis = asset->getDescendant("up_axis");
if (upAxis && upAxis->getCharData() == "Z_UP")
    // We have a match!

Child elements

If you know the name of the child element you want, you can access it with daeElement::getChild.

daeElement* getChild(daeString eltName);

This will return null if the element with the given name doesn't exist. You might use this function to test for the existence of a particular child element.

if (root->getChild("asset") == NULL)
    cout << "Missing <asset> element!\n"

If you don't have a specific element in mind you can get a list of all the child elements instead with the daeElement::getChildren method.

daeTArray< daeSmartRef<daeElement> > getChildren();

It returns an array of smart pointers to daeElement objects, which you can simply treat like ordinary daeElement pointers. You can use daeElement::getChildren to print a list of all the child elements of root like this.

daeTArray<daeElementRef> children = root->getChildren();
for (size_t i = 0; i < children.getCount(); i++)
	cout << "child " << i << " name: " << children[i]->getElementName() << endl;

daeElementRef is just a typedef for daeSmartRef<daeElement> that's made available to DOM clients to keep code simpler.