The R Project SVN R-packages

Rev

Blame | Last modification | View Log | Download | RSS feed

#include <libxml/tree.h>

#include "RSCommon.h"
#include "RS_XML.h"

#define R_USE_XML_ENCODING 1
#include "Utils.h"  /* R_createXMLNodeRef, Encoding macros. */

// need to release any <dummy> namespace.


int fixDummyNS(xmlNodePtr node, int recursive);
int setDummyNS(xmlNodePtr node, const xmlChar *prefix);
xmlNs *findNSByPrefix(xmlNodePtr node, const xmlChar *prefix);

SEXP
R_fixDummyNS(SEXP r_node, SEXP r_recursive)
{
    xmlNodePtr node;
    int status;
    node = (xmlNodePtr) R_ExternalPtrAddr(r_node);  
    status = fixDummyNS(node, LOGICAL(r_recursive)[0]);
    return(ScalarInteger(status));
}

int
fixDummyNS(xmlNodePtr node, int recursive)
{
    xmlNs *ns = node->ns;
    int count = 0;

    if(ns && strcmp((const char *)ns->href, "<dummy>") == 0)
    count = setDummyNS(node, ns->prefix);

    if(recursive)  {
    xmlNodePtr ptr = node->children;
    while(ptr) {
        count += fixDummyNS(ptr, recursive);
        ptr = ptr->next;
    }
    }

    return(count);
}

int
setDummyNS(xmlNodePtr node, const xmlChar *prefix)
{
    xmlNodePtr a = node->parent;
    while(a) {
    xmlNs *ns;
    ns = findNSByPrefix(a, prefix);
    if(ns) {
#ifdef R_XML_DEBUG
        fprintf(stderr, "mapping %s to %s\n", prefix, ns->href);fflush(stderr);
#endif
        node->nsDef = node->nsDef->next;
        xmlSetNs(node, ns);
        return(1);
    }
    a = a->parent;
    }
    return(0);
}


xmlNs *
findNSByPrefix(xmlNodePtr node, const xmlChar *prefix)
{
    xmlNs *ptr = node->nsDef;
    while(ptr) {
    if((!prefix || !prefix[0]) && !ptr->prefix)
        return(ptr);

    if(prefix && ptr->prefix && strcmp((const char *)ptr->prefix, (const char *)prefix) == 0)
        return(ptr);
    ptr = ptr->next;
    }

    return(NULL);
}


void
setDefaultNs(xmlNodePtr node, xmlNsPtr ns, int recursive)
{
    if(!node->ns)
    xmlSetNs(node, ns);
    if(recursive) {
    xmlNodePtr cur = node->children;
    while(cur) {
        setDefaultNs(cur, ns, 1);
        cur = cur->next;
    }
    }
}


SEXP
R_getAncestorDefaultNSDef(SEXP r_node, SEXP r_recursive)
{
   xmlNodePtr cur, node;
   xmlNs *ans = NULL;
   cur = (xmlNodePtr) R_ExternalPtrAddr(r_node);

   node = cur->parent;

   while(node && (node->type != XML_DOCUMENT_NODE && 
          node->type != XML_HTML_DOCUMENT_NODE)) {  /* Need to check for HTML_DOC or XML_DOC ?*/
       ans = findNSByPrefix(node, NULL);
       if(ans)
       break;
       node = node->parent;
   }

   if(ans) {
       xmlSetNs(cur, ans);
       if(LOGICAL(r_recursive)[0]) {
       setDefaultNs(cur, ans, 1);
       }
       return(ScalarLogical(1)); // R_createXMLNsRef(ans));
   }

   return(R_NilValue);
}