How to add a xml node constructed from string in libxml2

后端 未结 4 615
栀梦
栀梦 2021-02-09 13:34

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 \"<\

相关标签:
4条回答
  • 2021-02-09 13:46

    You have to call xmlNewChild in a chain, one call for the parent node and a call each for each sub-node:

    xmlNodePtr *addressNode = xmlNewChild(node, NULL, (xmlChar *) "address", NULL);
    xmlNewChild(addressNode, NULL, (xmlChar *) "street", "Park Street");
    xmlNewChild(addressNode, NULL, (xmlChar *) "city", "Koltaka");
    
    0 讨论(0)
  • 2021-02-09 13:48

    You can try to use function xmlParseInNodeContext. It allows you to parse raw XML in the context of parent node, and constructs a node that can be attached to the parent.

    For example:

    const char * xml = "<a><b><c>blah</c></b></a>";
    xmlNodePtr new_node = NULL;
    
    // we assume that 'parent' node is already defined
    xmlParseInNodeContext(parent, xml, strlen(xml), 0, &new_node);
    if (new_node) xmlAddChild(parent, new_node);
    
    0 讨论(0)
  • 2021-02-09 14:10

    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);
    }
    
    0 讨论(0)
  • 2021-02-09 14:12

    I'm now using the following code to inject XML text (possibly containing multiple elements) into an existing node (thanks to Nazar and nwellnhof for the one answer and referring me from my question (Injecting a string into an XML node without content escaping) to this one):

    std::string xml = "<a>" + str + "</a>";
    xmlNodePtr pNewNode = nullptr;
    xmlParseInNodeContext(pParentNode, xml.c_str(), (int)xml.length(), 0, &pNewNode);
    if (pNewNode != nullptr)
    {
        // add new xml node children to parent
        xmlNode *pChild = pNewNode->children;
        while (pChild != nullptr)
        {
            xmlAddChild(pParentNode, xmlCopyNode(pChild, 1));
            pChild = pChild->next;
        }
    
        xmlFreeNode(pNewNode);
    }
    

    It takes the string (str) adds a surrounding element (< a >...< a/ >), parses the string using xmlParseInNodeContext and then adds the children of the new node to the parent. It is important to add the children of the new node and not the new node to avoid having < a >...< a/ > in the final XML.

    0 讨论(0)
提交回复
热议问题