Search code examples
cxmllibxml2

How to add a xml node constructed from string in libxml2


I am using Libxml2 for encoding the data in a xml file. My data contain tags like "<" and ">". when it is converted into xml these tags are also converted into "&lt" and "&gt". Is there any way to solve this problem. I want to use those tags as xml nodes while decoding that xml file, so CDATA is not a solution for this problem. Please give any solution for this. Thanks.

Example Code:

xmlNewChild(node, NULL, (xmlChar *)"ADDRESS", (xmlChar *)"<street>Park Street</street><city>kolkata</city>");

and output of above code is:
<person>
<ADDRESS>&lt;street&gt;Park Street&lt;/street&gt;&lt;city&gt;Kolkata&lt;/city&gt;</ADDRESS>

Solution

  • If you want a string to be treated as xml, then you should parse it and obtain xmlDoc from it, using xmlReadMemory. It could be usable for larger strings, but usually the document is builded using single step instructions, like in Joachim's answer. Here I present xmlAddChildFromString function to do the stuff in a string way.

    #include <stdio.h>
    #include <string.h>
    #include <libxml/parser.h>
    #include <libxml/tree.h>
    
    /// Returns 0 on failure, 1 otherwise
    int xmlAddChildFromString(xmlNodePtr parent, xmlChar *newNodeStr)
    {
      int rv = 0;
      xmlChar *newNodeStrWrapped = calloc(strlen(newNodeStr) + 10, 1);
      if (!newNodeStrWrapped) return 0;
      strcat(newNodeStrWrapped, "<a>");
      strcat(newNodeStrWrapped, newNodeStr);
      strcat(newNodeStrWrapped, "</a>");
      xmlDocPtr newDoc = xmlReadMemory(
        newNodeStrWrapped, strlen(newNodeStrWrapped),
        NULL, NULL, 0);
      free(newNodeStrWrapped);
      if (!newDoc) return 0;
      xmlNodePtr newNode = xmlDocCopyNode(
        xmlDocGetRootElement(newDoc),
        parent->doc,
        1);
      xmlFreeDoc(newDoc);
      if (!newNode) return 0;
      xmlNodePtr addedNode = xmlAddChildList(parent, newNode->children);
      if (!addedNode) {
        xmlFreeNode(newNode);
        return 0;
      }
      newNode->children = NULL; // Thanks to milaniez
      newNode->last = NULL;     // for fixing
      xmlFreeNode(newNode);     // the memory leak.
      return 1;
    }
    
    int
    main(int argc, char **argv)
    {
        xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
        xmlNodePtr root = xmlNewNode(NULL, BAD_CAST "root");
        xmlDocSetRootElement(doc, root);
        xmlAddChildFromString(root,
          "<street>Park Street</street><city>kolkata</city>");
        xmlDocDump(stdout, doc);
        xmlFreeDoc(doc);
        return(0);
    }