[xml] libxml missing tree_walker?
- From: "Morten S. Christensen" <mschr es aau dk>
- To: xml gnome org
- Subject: [xml] libxml missing tree_walker?
- Date: Thu, 08 May 2008 02:57:57 +0200
Hi
Ive been a bit back and forth through the reference manual, and usually
end up in the Tree API. What ive been missing though, is a way to
traverse the document for a particular node. Now, i know xpath might do
the trick, but then one would have to inlcude more headers and extract
the path at first. While operating a tree, one can easier get the root
from the document and walk a bit back n forth till the right node pops
up in your 'hands' :)
So i wrote this little recursive tree search, which i'd like to share;
set/get message is just placed in a buffer string, suit error handling
to your needs.
ï
#include <libxml/tree.h>
#include <stdio.h>
xmlDocPtr g_doc;
xmlNodePtr search_result;
int cur_depth = 0;
int validate(xmlNodePtr node)
{
int x = node->type;
// just a few types of nodes, i wouldnt be too interested in
if(x != XML_TEXT_NODE
&& x != XML_NAMESPACE_DECL
&& x != XML_CDATA_SECTION_NODE
&& x != XML_COMMENT_NODE) {
return 1;
} else {
return 0;
}
}
int lookup_node(xmlNodePtr node, const char * search_id, int max)
{
while(node)
{
if(validate(node))
{
if(xmlStrEqual(node->name, (xmlChar *) search_id) )
{
search_result = node;
return 1;
}
}
if(node->children && cur_depth < max) {
cur_depth++;
if(lookup_node(node->children, search_id, max) )
return 1;
}
node = node->next;
} // WHILE siblings
cur_depth--;
return 0;
}
char *node_as_xml(const char * search_id, int search_depth)
{
search_result = NULL;
xmlBufferPtr buf = xmlBufferCreate();
xmlNodePtr node = xmlDocGetRootElement(g_doc);
while (node)
{ // ROOT sibling loop
if(validate(node))
{
if( xmlStrEqual(node->name,(xmlChar *)search_id) ) {
search_result = node;
break;
}
}
if(node->children)
{
if(lookup_node(node->children, search_id,search_depth) )
break;
}
node = node->next;
}
if(search_result) { // Success!
if(xmlNodeDump(buf, g_doc, search_result, 0, 1))
{
search_result = NULL;
return (char *) xmlBufferContent(buf);
} else {
//set_message("node_as_xml: FAILED buffering node in query\n");
return NULL;
}
} else { // failed..
//set_message("node_as_xml: FAILED in search, no such node in tree
\n");
return NULL;
}
}
/* Example usage: */
int main(void)
{
g_doc = xmlNewDoc(BAD_CAST "1.0");
xmlNodePtr root = xmlNewNode(NULL, BAD_CAST "aRoot");
xmlDocSetRootElement(g_doc, root);
xmlNewChild(root, NULL, BAD_CAST "1", NULL);
xmlNewChild(root, NULL, BAD_CAST "2", NULL);
xmlNewChild(root, NULL, BAD_CAST "3", NULL);
xmlNodePtr node = xmlNewChild(root, NULL, BAD_CAST "4", NULL);
xmlNewChild(node, NULL, BAD_CAST "4_1", NULL);
xmlNewChild(node, NULL, BAD_CAST "4_2", BAD_CAST "tryme");
/*
* We look for a node, lookup_node is called recursively while there are
* children. Second parameter is a maximum depth for recursion - we dont
* care here, but large trees might need the option
* First occurence found is return as a char *, which is unfortunately
* never free'd though. Alternatively, return the search_result node
* from 'node_as_xml' function.
*/
char * subtree = node_as_xml("4_2", 999);
printf("Recursive contents from '4_2'-node \n%s\n", subtree);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]