Tutorial
This is a short C++ example of parsing with AsmXml.
This tutorial does not show a complete code, it shows only the library related parts and ignores error code to be more concise and focus on the main structure. There is more complete examples in the distribution.
1. The Goal
We'd like to parse an XML document like this one:
<?xml version="1.0"?> <employees> <employee id="001"> <firstName>Brian</firstName> <lastName>Williams</lastName> </employee> <employee managerId="001" id="123"> <lastName>Smith</lastName> <firstName>John</firstName> </employee> ... </employees>
2. Defining the schema
To parse it, we must define a schema in order to get direct access to values without lookup.
The document is just a collection of <employee> elements with two attributes and two text elements, the schema should looks like:
<schema> <document name="employees"> <collection name="employee"> <attribute name="id"/> <attribute name="managerId"/> <text name="firstName"/> <text name="lastName"/> </collection> </document> </schema>
Let's save this in a file named employees-schema.xml.
3. Parsing the file
The first thing to do is to initialize the library, it must done once for all in the application session:
ax_initialize(malloc, free);
The next thing to do is to load the schema. We first need a AXClassContext object to parse and stores schema, then we can use the ax_classFromString function to create the class. All classes created in a AXClassContext will remains available until the context is released. Let's assume that the schema is loaded at schemaPtr:
AXClassContext classContext; ax_initializeClassParser(&classContext); AXElementClass* rootClass = ax_classFromString(schemaPtr, &classContext);
It's time to parse the document. An AXParseContext object must be first created and initialized. It will store all documents parsed in memory until the context is released. Let's assume that the xml is loaded at xmlPtr:
AXParseContext context; ax_initializeParser(&context, 16384); AXElement* root = ax_parse(&context, xmlPtr, rootClass);
4. Exploring the Document
Now we have the document parsed into an in-memory structure, similar to a DOM element, but far more effecient to exploration. Children are enumerated using the firstChild and nextSibling attributes, attributes are directly accessed using the attributes array.
AXElement* employee = root->firstChild; while( employee ) { printf("Id.........: %s\n", asString(&employee->attributes[0])); printf("Manager....: %s\n", asString(&employee->attributes[1])); printf("First Name.: %s\n", asString(&employee->attributes[2])); printf("Last Name..: %s\n", asString(&employee->attributes[3])); employee = employee->nextSibling; }
asString is just a function to convert attributes (pair of begin/end pointers) to zero terminated strings.
In this example,
- attributes[0] corresponds to the id attribute since it is the first one defined in the employee collection in the schema,
- attributes[1] corresponds to the managerId attribute since it arrives in second place in the schema,
- attributes[2] corresponds to the firstName element since it arrives in third place,
- ...
5. Cleaning Things Up
Once we have finished, the parse context can be freed, it will release all resources allocated by the elements parsed with this context. The class context can also be freed, it will release all resources used by the schema.
ax_releaseParser(&context); ax_releaseClassParser(&classContext);