Xml in C

Here’s the translation of the XML handling code from Go to C, formatted in Markdown suitable for Hugo:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libxml/parser.h>
#include <libxml/tree.h>

// Plant structure to be mapped to XML
typedef struct {
    int id;
    char *name;
    char **origin;
    int origin_count;
} Plant;

// Function to create a string representation of a Plant
char* plant_to_string(Plant *p) {
    char *result = malloc(256 * sizeof(char));
    sprintf(result, "Plant id=%d, name=%s, origin=[", p->id, p->name);
    for (int i = 0; i < p->origin_count; i++) {
        strcat(result, p->origin[i]);
        if (i < p->origin_count - 1) {
            strcat(result, " ");
        }
    }
    strcat(result, "]");
    return result;
}

int main() {
    // Initialize the library
    LIBXML_TEST_VERSION

    // Create a Plant instance
    Plant coffee = {27, "Coffee", (char*[]){"Ethiopia", "Brazil"}, 2};

    // Create an XML document
    xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
    xmlNodePtr root_node = xmlNewNode(NULL, BAD_CAST "plant");
    xmlDocSetRootElement(doc, root_node);

    // Set attributes and child nodes
    char id_str[10];
    sprintf(id_str, "%d", coffee.id);
    xmlNewProp(root_node, BAD_CAST "id", BAD_CAST id_str);

    xmlNewChild(root_node, NULL, BAD_CAST "name", BAD_CAST coffee.name);

    for (int i = 0; i < coffee.origin_count; i++) {
        xmlNewChild(root_node, NULL, BAD_CAST "origin", BAD_CAST coffee.origin[i]);
    }

    // Save the document to a string
    xmlChar *xmlbuff;
    int buffersize;
    xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);

    printf("%s\n", (char *)xmlbuff);

    // Parse the XML string back into a document
    xmlDocPtr doc2 = xmlReadMemory((char *)xmlbuff, buffersize, "noname.xml", NULL, 0);
    if (doc2 == NULL) {
        fprintf(stderr, "Failed to parse document\n");
        return 1;
    }

    // Extract data from the parsed document
    xmlNodePtr root = xmlDocGetRootElement(doc2);
    Plant p = {0};
    p.id = atoi((char *)xmlGetProp(root, BAD_CAST "id"));
    xmlNodePtr cur = root->children;
    while (cur != NULL) {
        if ((!xmlStrcmp(cur->name, (const xmlChar *)"name"))) {
            p.name = (char *)xmlNodeListGetString(doc2, cur->xmlChildrenNode, 1);
        } else if ((!xmlStrcmp(cur->name, (const xmlChar *)"origin"))) {
            p.origin = realloc(p.origin, (p.origin_count + 1) * sizeof(char *));
            p.origin[p.origin_count] = (char *)xmlNodeListGetString(doc2, cur->xmlChildrenNode, 1);
            p.origin_count++;
        }
        cur = cur->next;
    }

    char *p_str = plant_to_string(&p);
    printf("%s\n", p_str);
    free(p_str);

    // Clean up
    xmlFree(xmlbuff);
    xmlFreeDoc(doc);
    xmlFreeDoc(doc2);
    xmlCleanupParser();

    return 0;
}

This C code demonstrates XML handling using the libxml2 library. Here’s a breakdown of what the code does:

  1. We define a Plant structure to represent our data.

  2. The plant_to_string function creates a string representation of a Plant.

  3. In the main function:

    • We create a Plant instance.
    • We create an XML document representing the Plant.
    • We save the XML document to a string and print it.
    • We parse the XML string back into a document.
    • We extract data from the parsed document into a new Plant instance.
    • We print the string representation of the parsed Plant.
  4. Throughout the code, we use libxml2 functions for XML operations:

    • xmlNewDoc, xmlNewNode, xmlDocSetRootElement for creating XML documents.
    • xmlNewProp, xmlNewChild for adding attributes and child nodes.
    • xmlDocDumpFormatMemory for saving the XML to a string.
    • xmlReadMemory for parsing XML from a string.
    • xmlGetProp, xmlNodeListGetString for extracting data from XML nodes.
  5. We clean up allocated resources at the end of the program.

Note that error handling has been simplified in this example. In a production environment, you would want to add more robust error checking and handling.

To compile and run this program, you’ll need to have libxml2 installed and link against it. For example:

$ gcc -o xml xml.c `xml2-config --cflags --libs`
$ ./xml

This will output the XML representation of the Plant and then the string representation of the Plant parsed from that XML.