Posts Tagged ‘C’

Parsing XML files with APR

August 17th, 2009

I wanted to write an XML parser for one of my personal projects, and I needed to use Apache APR for this. Since I did not find any example about doing this on the web I thought it might be a good idea to write a short tutorial about this. Maybe it could be helpful to someone else.

Let’s prepare the tutorial, we need a XML file, for example this one example.xml :
<?xml version="1.0" encoding="utf-8"?>
<document>
<a someattribute="attribute of A">
<b>the value of B</b>
</a>
</document>

And a Makefile, for example this one :

APR_CONFIG=$(shell which apr-1-config)
CC=gcc
CXX=g++
CFLAGS=$(shell ${APR_CONFIG} --cflags --cppflags --includes) -Wall
CXXFLAGS=$(shell ${APR_CONFIG} --cflags --cppflags --includes) -Wall
LDFLAGS=$(shell ${APR_CONFIG} --ldflags)
LDLIBS=$(shell ${APR_CONFIG} --libs --link-ld) -laprutil-1

Now the parser, parse.c:

#ifdef HAVE_CONFIG_H
#include
#endif

#include
#include

#include
#include

/**
* Dumps an XML document
*/
static void dump_xml( apr_xml_elem *e, apr_pool_t *pool )
{
apr_xml_elem *child_element;
const char *text;

if ( e->attr )
{
printf( "This tag has an attribute : <%s %s=%s>\n", e->name, e->attr->name, e->attr->value );
}

if (e->first_child)
{
child_element = e->first_child;

while (child_element)
{
printf( "<%s> --> ", child_element->name );
if( !APR_XML_ELEM_IS_EMPTY( child_element ) )
{
apr_xml_to_text( pool, child_element, APR_XML_X2T_INNER, NULL, NULL, &text, NULL);
printf( "%s\n", text );
}
dump_xml( child_element, pool );
child_element = child_element->next;
}
}
}

/**
* Process an XML file
* @return APR_SUCCESS if success, otherwise -1
*/
static int process_xml_file( const char *filename, apr_pool_t *pool )
{
apr_file_t *fp;
apr_status_t rv;
apr_xml_parser *parser;
apr_xml_doc *doc;
char *errbuf;

if ( ( rv = apr_file_open( &fp, filename, APR_FOPEN_READ, APR_OS_DEFAULT, pool ) ) != APR_SUCCESS ) {
return -1;
}

rv = apr_xml_parse_file( pool, &parser, &doc, fp, 2000 );

if( rv != APR_SUCCESS )
{
printf( "Error : %s", apr_xml_parser_geterror( parser, errbuf, 255 ) );
return -1;
}

dump_xml( doc->root, pool );

return APR_SUCCESS;
}

int main(int argc, char **argv)
{
apr_pool_t *pool;
const char *filename;

if ( argc == 2 )
{
filename = argv[1];
}
else
{
filename = "example.xml";
}

apr_initialize();
apr_pool_create( &pool, NULL );

process_xml_file( filename, pool );

apr_terminate();
return 0;
}

Now store example.xml and parse.c in the same directory and build parse.c

make parse && ./parse filename.xml

You should get the following result:
<a> -->
<b>the value of B</b>

This tag has an attribute : <a someattribute=attribute of A>
<b> --> the value of B

Some useful documentation :

You can dowload the files here

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)