Question

I have a very weird error with the xmlNewChild function using libxml2. I tried to keep the post as short as possible so I removed some insignificant logic. A boolean variable is defined for each variable to be written and when setting the variable value, the boolean is set to TRUE indicating if the tag is present, and if it is, it's written, otherwise is skipped

I have defined a structure as follows:

 tyedef struct _xml_parse_t
 {
    const char   *name;
    void         *variable;
    int          type;
    _xml_parse_t *childs;
 } xml_parse_t;

Another function parses this structure and writes it to a char*. the function is defined as follows:

int generate_xml(xml_parse_t *p, char *out, const char*root)
{
    xmlChar *s = NULL;
    int size = 0;

    xmlDocPtr doc = NULL;
    xmlNodePtr root_node = NULL;

    doc = xmlNewDoc(NULL);
    if(NULL == doc)
        return -1;
    root_node = xmlNewNode(NULL, BAD_CAST root);
    if(NULL == root_node)
        return -1;
    else
        xmlDocSetRootElement(doc, root_node);

    if(-1 == writeXmlToDoc(p, doc, root_node))
        return -1;

    xmlDocDumpFormatMemoryEnc(doc, &s, &size, "UTF-8", 1);

    if(NULL == s)
        return -1;

    if(SUCCEED == ret)
        strcpy(out, (char *)s);

    if(NULL != s)
        xmlFree(s);

    xmlFreeDoc(doc);
    xmlCleanupParser();
    xmlMemoryDump();

    return 0;
}

The writeXmlToDoc is defined as below

int writeXmlToDoc(xml_parse_t *parse, xmlDocPtr doc, 
            xmlNodePtr root_node)
{
    xml_parse_t *p = parse;
    xmlNodePtr node;

    while(NULL != p->name)
    {
        if( NODE_TYPE_PARENT == p->type && NULL != p->childs)
        {
            node = xmlNewChild(root_node, NULL, BAD_CAST p->name, NULL);
            if(-1 == writeXmlToDoc(p->childs, doc, node))
                return -1;
        }
        else
        {
            printf("Current value being written [%s]", (char *)cvtToXmlChar(p->variable, p->type));
            node = xmlNewChild(root_node, NULL, BAD_CAST p->name,
                BAD_CAST cvtToXmlChar(p->variable, p->type));

        }       
        p++;
    }

    return 0;
}

To keep this post as short as possible, the cvtToXmlChar checks the type of the variable and casts it to xmlChar and the printf before the xmlNewChild is showing correct value of the variable.

xml_parse_t child_parse[] = {
   /* Name           var          Type              Childs*/
    {"ChildInt",     &test_int1,   NODE_TYPE_INT,    NULL },
    {"ChildLong",    &test_long1,  NODE_TYPE_LONG,   NULL },
    {"ChildChar",    test_char1,  NODE_TYPE_STRING, NULL },
    {"ChildShort",   &test_short1, NODE_TYPE_SHORT,  NULL },
    {"ChildDouble",  &test_double1,NODE_TYPE_DOUBLE, NULL },
    { NULL }
};

xml_parse_t parent_parse[] = {
   /* Name           var          Type              Childs*/
    {"ParentInt",    &test_int,    NODE_TYPE_INT,    NULL        },
    {"ParentLong",   &test_long,   NODE_TYPE_LONG,   NULL        },
    {"ParentChar",   test_char,   NODE_TYPE_STRING, NULL        },
    {"ParentShort",  &test_short,  NODE_TYPE_SHORT,  NULL        },
    {"ParentDouble", &test_double, NODE_TYPE_DOUBLE, NULL        },
    {"ParentParent", NULL,        NODE_TYPE_PARENT, child_parse },
    { NULL }
};

and the variables set as follows:

 test_int = 1;  
 test_int1 = 2;
 test_long = 1;
 test_long1 = 2; 
 sprintf(test_char, "TestParentCharTag"); 
 sprintf(test_char1, "TestChildCharTag");
 test_short = 1;
 test_short1 = 2;
 test_double = 1;
 test_double1 = 2;

The problem is, the output string has 2 missing values. Following is the output of running the test

 <ROOTELEMENT>
   <ParentInt>1</ParentInt>
   <ParentLong></ParentLong>
   <ParentChar>TestParentCharTag</ParentChar>
   <ParentShort>1</ParentShort>
   <ParentDouble>1.000000</ParentDouble>
   <ParentParent>
     <ChildInt></ChildInt>
     <ChildLong>2</ChildLong>
     <ChildChar>TestChildCharTag</ChildChar>
     <ChildShort>2</ChildShort>
     <ChildDouble>2.000000</ChildDouble>
   </ParentParent>
 </ROOTELEMENT>
Was it helpful?

Solution

I'm not sure why but I had to use

  xmlNodeSetContent(node, BAD_CAST cvtToXmlChar(variable, type));

after using the xmlNewChild.

I'm not sure about this solution (it's not really the best one) but it did the trick.

I still appreciate if I can get an explanation on the behavior above.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top