In the context of libxml2, here's a general approach that handles preorder and postorder traversal. As @chqrlie noted, libxml2 stores a pointer to the parent node, so you can iterate a subtree using constant memory.
typedef void
(*callbackFn)(xmlNode *cur, void *data);
void
iterateSubtree(xmlNode *cur,
callbackFn callbackPreorder,
callbackFn callbackPostorder,
void *data) {
xmlNode *orig;
if (!cur)
return;
orig = cur;
do {
callbackPreorder(cur, data);
while (cur->children) {
cur = cur->children;
callbackPreorder(cur, data);
}
while (cur != orig) {
// Storing a copy of next and parent allows the postorder
// callback to append to or delete a node.
xmlNode *next = cur->next;
xmlNode *parent = cur->parent;
callbackPostorder(cur, data);
if (next) {
cur = next;
break;
}
cur = parent;
}
} while (cur != orig);
callbackPostorder(cur, data);
}