Re: [xml] trying to build a document with a shared dictionary



Hey,

I'll take the opportunity to bring up this older issue again that I ran into. You suggested then to use shared dictionaries between documents to avoid a memory problem when moving nodes from one document to another.

Martijn Faassen wrote:

One of the suggestions made to solve my node moves into other document problem is to make sure all documents share their dictionaries. The following code is my attempt, but valgrind is still not happy when freeing the documents:

#include "libxml/tree.h"
#include "libxml/parser.h"

/* parse document in context of document, sharing its dictionary */
static xmlDocPtr xmlSharedDictReadDoc(const xmlDocPtr doc,
                                      const xmlChar* text) {
  xmlParserCtxtPtr pctxt;
  xmlDocPtr ret;

  xmlInitParser();

  /* parse from text in memory */
  pctxt = xmlCreateDocParserCtxt(text);

  /* make sure dictionary is shared with doc's */
  if ((doc != NULL) && (doc->dict != NULL) && (pctxt->dict != NULL)) {
    xmlDictFree(pctxt->dict);
    pctxt->dict = doc->dict;
    xmlDictReference(pctxt->dict);
  }

  /* no net-loads, no entity expansion */
  xmlCtxtUseOptions(pctxt, XML_PARSE_NONET | XML_PARSE_NOENT);

  /* parse document */
  xmlParseDocument(pctxt);

  if (pctxt->wellFormed) {
    ret = pctxt->myDoc;
  }
  else {
    ret = NULL;
    if (pctxt->myDoc != NULL)
      xmlFreeDoc(pctxt->myDoc);
    pctxt->myDoc = NULL;
  }
  xmlFreeParserCtxt(pctxt);

  return(ret);
}

int main() {
  xmlDoc* doc1;
  xmlDoc* doc2;
  xmlNode* node;
  xmlChar* text = "<doc>foo</doc>";

  /* parse the first document */
  doc1 = xmlSharedDictReadDoc(NULL, text);
  /* parse the second document, sharing dictionary of the first */
  doc2 = xmlSharedDictReadDoc(doc1, text);

  /* get the root node of the first document */
  node = xmlDocGetRootElement(doc1);
  /* set the root element in the other document */
  xmlDocSetRootElement(doc2, node);
  /* not sure whether xmlSetTreeDoc is necessary */
  xmlSetTreeDoc(node, doc2);
  /* reconciliate namespaces; shouldn't matter in this case */
  xmlReconciliateNs(doc2, node);
  /* now free both documents */
  xmlFreeDoc(doc1);
  xmlFreeDoc(doc2);
}

Any suggestions? I rather lost in the parser APIs, so I may very well be doing something wrong.

Regards,

Martijn



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]