Analisando arquivos XML locais e remotos com libxml2. 

libxml2 é uma biblioteca de software feita para  analisar documentos XML , escrita em C e disponibilizada sob a licença MIT. Mesmo construído em  C, fornece “ligações” para outras linguagens.

A biblioteca também é conhecida pela portabilidade, compilação fácil e alta velocidade.

A instalação através dos repositórios do Debian fica:

$ sudo apt-get install libxml2-dev

O código abaixo foi escrito para analisar arquivos remotos ou locais, ele fazia parte de um projeto que eu estava desenvolvendo para buscar músicas no site 4shared, mas foi descontinuado.

Como a postagem não trata-se de tutorial, vou dispensar as explicações. O código é pequeno e de fácil compreensão após breve exercício mental.

Recomendo a leitura da documentação oficial da libxml2.

Para compilar:

$ gcc $(xml2-config --cflags --libs) ./parse.c -o ./parse

O layout do arquivo XML analisado pelo código é:

<!-- ROOT -->
<search-result>
	<!-- MAIN -->
	<query/>
	<total-files>8975</total-files>
	<page-number>1</page-number>
	<pages-total>897</pages-total>
	<start>0</start>
	<files-per-page>10</files-per-page>
	<files-approx-count>16219367</files-approx-count>
	<!-- FILE -->
	<result-files>
		<file>
			<name>Foo</name>
		</file>
		<file>
			<name>Bar</name>
		</file>
		<file>
			<name>Qux</name>
		</file>
	</result-files>
</search-result>

O mesmo modelo é usado no documento gerado na página: https://search.4shared.com/network/searchXml.jsp

O programa:

#include <stdio.h>
#include <stdlib.h>
 
#include <libxml/tree.h>
#include <libxml/parser.h>
 
/*
 * Copyright (C) 2014 Fm4lloc <fm4lloc@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 */
 
void cleanAll(xmlDocPtr doc)
{
    xmlFreeDoc (doc);
    /*
     * Free the global variables that may
     * have been allocated by the parser.
     */
    xmlCleanupParser ();
}
 
void printXmlContent (xmlDocPtr doc, xmlNodePtr cur)
{
    xmlChar *key = NULL;
 
    if ((key = xmlNodeListGetString (doc,
        cur->xmlChildrenNode, 1)))
    {
        printf("%s\n", key);
        xmlFree (key);
    }
}
 
static void eachFile (xmlDocPtr doc, xmlNodePtr cur)
{
    cur = cur->xmlChildrenNode;
    while (cur != NULL)
    {
        /* <search-result>
         *      ...
         *      <result-files>
         *          <file>
         *              <name>
         */
        if ((!xmlStrcmp (cur->name, (const xmlChar *) "name")))
            printXmlContent (doc, cur);
 
        cur = cur->next;
    }
}
 
static void parseFile (xmlDocPtr doc, xmlNodePtr cur)
{
    cur = cur->xmlChildrenNode;
    while (cur != NULL)
    {
        if ((!xmlStrcmp (cur->name, (const xmlChar *) "file")))
            eachFile (doc, cur);
 
        cur = cur->next;
    }
}
 
static void parseMainInfo (xmlDocPtr doc, xmlNodePtr cur)
{
    cur = cur->xmlChildrenNode;
    while (cur != NULL)
    {
            if (cur->type == XML_ELEMENT_NODE)
            {
                /* Stop when you find the node: result-files */
                if ((!xmlStrcmp (cur->name, (const xmlChar *) "result-files")))
                    break;
 
                printXmlContent (doc, cur);
            }       
 
        cur = cur->next;
    }
}
 
/**
 * parseDoc:
 * @filename: A filename or an URL
 *
 * Parse XML
 *
 * Returns int
 */
static int parseDoc (const char *filename)
{
    xmlDocPtr  doc = NULL;
    xmlNodePtr cur = NULL;
 
    doc = xmlReadFile (filename, NULL, 0);
    if (doc == NULL)
    {
            fprintf (stderr, "Document not parsed.\n");
            return 1;
    }
 
    /* Get the root element node */
    cur = xmlDocGetRootElement(doc);
    if (cur == NULL)
    {
            fprintf (stderr,"empty document\n");
            cleanAll (doc);
            return 1;
    }
 
    /* Check if node root == "search-result" */
    if (xmlStrcmp (cur->name, (const xmlChar *) "search-result"))
    {
            fprintf (stderr,"document of the wrong type, root node != %s\n", cur->name);
            cleanAll (doc);
            return 1;
    }
 
    /* <search-result> */
    parseMainInfo (doc, cur);
 
    /* <search-result>
     *      ...
     *      <result-files> */
    cur = cur->xmlChildrenNode;
    while (cur != NULL)
    {
        if ((!xmlStrcmp (cur->name, (const xmlChar *) "result-files")))
        {
        /* <search-result>
         *      <result-files>
         *          <file>
         */
            parseFile (doc, cur);
        }
 
        cur = cur->next;
    }
 
    cleanAll (doc);
 
    return 0;
}
 
int main(void)
{
    if (parseDoc ("./content.xml") != 0)
        return -1;
 
    return 0;
}

Saída padrão:

8975
1
897
0
10
16219367
Foo
Bar
Qux