"Fossies" - the Fresh Open Source Software Archive

Member "rpm2html-1.11.2/rdf_api.c" (5 Oct 2010, 15505 Bytes) of package /linux/privat/rpm2html-1.11.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "rdf_api.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * rdf_api.h : implementation of methods to read and write RDF schemas
    3  *
    4  * See Copyright for the status of this software.
    5  *
    6  * $Id: rdf_api.c,v 1.30 2010/10/05 14:36:54 hany Exp $
    7  */
    8 
    9 #include "config.h"
   10 #include <stdio.h>
   11 #include <string.h>
   12 #include <errno.h>
   13 #include "rpm2html.h"
   14 #include "rpmdata.h"
   15 #include "rdf_api.h"
   16 /*
   17  * this module has been converted to libxml2, you need libxml2-devel or
   18  * older to compile it.
   19  */
   20 #include <libxml/xmlmemory.h>
   21 #include <libxml/parser.h>
   22 #include <libxml/tree.h>
   23 #include <libxml/parserInternals.h>
   24 
   25 /*
   26  * Reading an RDF schema stored in a file, this just build the
   27  * document tree, and check that it's an RDF:RDf element.
   28  */
   29 rdfSchema rdfRead(const char *filename) {
   30     xmlDocPtr res = NULL;
   31     int ret;
   32     xmlParserCtxtPtr ctxt;
   33     xmlSAXHandler silent, *old;
   34     xmlNodePtr root;
   35 
   36     /*
   37      * Do a silent call to the XML parser.
   38      */
   39     ctxt = xmlCreateFileParserCtxt(filename);
   40     if (ctxt == NULL) return(NULL);
   41     memcpy(&silent, ctxt->sax, sizeof(silent));
   42     old = ctxt->sax;
   43     silent.error = NULL;
   44     silent.warning = NULL;
   45     silent.fatalError = NULL;
   46     ctxt->sax = &silent;
   47 
   48     xmlParseDocument(ctxt);
   49 
   50     ret = ctxt->wellFormed;
   51     res = ctxt->myDoc;
   52     ctxt->sax = old;
   53     xmlFreeParserCtxt(ctxt);
   54 
   55     /*
   56      * This is not well formed.
   57      */
   58     if (!ret) {
   59     xmlFreeDoc(res);
   60     fprintf(stderr, "rdfRead %s: resource is not wellformed XML\n",
   61         filename);
   62     return(NULL);
   63     }
   64 
   65     root = xmlDocGetRootElement(res);
   66     if (root == NULL) {
   67     fprintf(stderr, "rdfRead %s: tree is empty\n", filename);
   68         xmlFreeDoc(res);
   69     return(NULL);
   70     }
   71     if (strcmp(root->name, "RDF")) {
   72     fprintf(stderr, "rdfRead %s: not an RDF file\n", filename);
   73         xmlFreeDoc(res);
   74     return(NULL);
   75     }
   76     return((rdfSchema) res);
   77 }
   78 
   79 /*
   80  * Writing an RDF schema to a file, this just save the
   81  * document tree as an XML document.
   82  */
   83 void rdfWrite(rdfSchema rdf, const char *filename) {
   84     FILE *output;
   85     
   86     output = fopen(filename, "w");
   87     if (output == NULL) {
   88         fprintf(stderr, "rdfWrite : couldn't save to file %s: %s\n",
   89             filename, strerror(errno));
   90         return;
   91     }
   92     xmlDocFormatDump(output, (xmlDocPtr) rdf, 1);
   93     fclose(output);
   94 }
   95 
   96 /*
   97  * Writing an RDF schema to a memory buffer, this just save the
   98  * document tree as an XML document.
   99  */
  100 void rdfWriteMemory(rdfSchema rdf, char **buffer, int *size) {
  101     xmlDocDumpMemory((xmlDocPtr) rdf, (xmlChar **) buffer, size);
  102 }
  103 
  104 /*
  105  * Creating an RDF schema tree in memory.
  106  */
  107 rdfSchema rdfNewSchema() {
  108     xmlDocPtr res;
  109     xmlNsPtr rdf;
  110    
  111     res = xmlNewDoc("1.0");
  112     res->xmlRootNode = xmlNewDocNode(res, NULL, "RDF", NULL);
  113     rdf = xmlNewNs(res->xmlRootNode, "http://www.w3.org/TR/WD-rdf-syntax#", "RDF");
  114     rdf = xmlNewNs(res->xmlRootNode, "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "rdf");
  115     xmlSetNs(res->xmlRootNode, rdf);
  116 
  117     return((rdfSchema) res);
  118 }
  119 
  120 /*
  121  * Adding a new namespace to an RDF schema.
  122  */
  123 rdfNamespace rdfNewNamespace(rdfSchema rdf, const char *url,
  124                              const char *namespace) {
  125     xmlNodePtr root;
  126     xmlNsPtr ns = NULL;
  127    
  128     root = xmlDocGetRootElement(rdf);
  129     if (root != NULL)
  130     ns = xmlNewNs(root, url, namespace);
  131 
  132     return((rdfNamespace) ns);
  133 }
  134 
  135 /*
  136  * Get a namespace associated to an RDF schema.
  137  * Should be stored either as an old NS on the document or as local
  138  * namespace stored on the root element.
  139  */
  140 rdfNamespace rdfGetNamespace(rdfSchema rdf, const char *href) {
  141     xmlNodePtr root;
  142 
  143     root = xmlDocGetRootElement(rdf);
  144     return((rdfNamespace) xmlSearchNsByHref(rdf, root, href));
  145 }
  146 
  147 /*
  148  * Get the RDF namespace associated to an RDF schema.
  149  */
  150 rdfNamespace rdfGetRdfNamespace(rdfSchema rdf) {
  151     rdfNamespace ns;
  152    
  153     ns = rdfGetNamespace(rdf, "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
  154     if (ns != NULL)
  155         return((rdfNamespace) ns);
  156     ns = rdfGetNamespace(rdf, "http://www.w3.org/TR/WD-rdf-syntax#");
  157     if (ns != NULL)
  158         return((rdfNamespace) ns);
  159     /* create it ! */
  160     return(rdfNewNamespace(rdf, "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "rdf"));
  161 }
  162 
  163 
  164 /*
  165  * Destroying an RDF schema in memory.
  166  */
  167 void rdfDestroySchema(rdfSchema rdf) {
  168     xmlFreeDoc((xmlDocPtr) rdf);
  169 }
  170 
  171 /**
  172  ** An RDF schema is a collection of RDF descriptions.
  173  ** The following are used to browse the list.
  174  **/
  175 
  176 /* First item */
  177 rdfDescription rdfFirstDescription(rdfSchema schema) {
  178     xmlNodePtr tree;
  179     rdfNamespace rdfNs;
  180 
  181     rdfNs = rdfGetRdfNamespace(schema);
  182     tree = xmlDocGetRootElement(schema);
  183     if (tree == NULL) return(NULL);
  184     tree = tree->xmlChildrenNode;
  185     while (tree != NULL) {
  186         if ((tree->ns == rdfNs) && (!strcmp(tree->name, "Description")))
  187         return(tree);
  188     tree = tree->next;
  189     }
  190     return(NULL);
  191 }
  192 
  193 /* Iteration : next item */
  194 rdfDescription rdfNextDescription(rdfDescription desc) {
  195     rdfNamespace rdfNs;
  196 
  197     if (desc == NULL) return(NULL);
  198     rdfNs = desc->ns;
  199     desc = desc->next;
  200     while (desc != NULL) {
  201         if ((desc->ns == rdfNs) && (!strcmp(desc->name, "Description")))
  202         return(desc);
  203     desc = desc->next;
  204     }
  205     return(NULL);
  206 }
  207 
  208 /*
  209  * Add an RDF description to an RDF schema, it just link it
  210  * the top level node of the description and requires further
  211  * action to fill it with the pertinent information.
  212  */
  213 rdfDescription rdfAddDescription(rdfSchema schema, const char *id,
  214                                  const char *about) {
  215     xmlNodePtr tree;
  216     xmlNodePtr root;
  217 
  218     root = xmlDocGetRootElement(schema);
  219     tree = xmlNewChild(root, NULL, "Description", NULL);
  220     if (id != NULL) {
  221         xmlNewProp(tree, "ID", id);
  222     }
  223     if (about != NULL) {
  224         if (oldXMLWDcompatibility) {
  225         rdfNamespace ns;
  226         char *buf;
  227 
  228         ns = rdfGetRdfNamespace(schema);
  229         buf = (char *) xmlMalloc(strlen(ns->prefix) + 10);
  230         sprintf(buf, "%s:HREF", ns->prefix);
  231         xmlNewProp(tree, buf, about); 
  232         xmlFree(buf);
  233         } else {
  234         xmlNewProp(tree, "about", about); 
  235     }
  236     }
  237     return((rdfDescription) tree);
  238 }
  239 
  240 /*
  241  * Read the attributes of a Description node.
  242  */
  243 char *rdfGetDescriptionId(rdfSchema schema, rdfDescription desc) {
  244     char *res;
  245 
  246     res = (char *) xmlGetProp(desc, "ID");
  247     return(res);
  248 }
  249 
  250 char *rdfGetDescriptionAbout(rdfSchema schema, rdfDescription desc) {
  251     char *res;
  252     rdfNamespace ns;
  253     char *buf;
  254 
  255     res = (char *) xmlGetProp(desc, "about");
  256     if (res != NULL) return(res);
  257 
  258     /*
  259      * Maintain compatibility with old "RDF:HREF"
  260      */
  261     res = (char *) xmlGetProp(desc, "HREF");
  262     if (res != NULL) return(res);
  263     ns = rdfGetRdfNamespace(schema);
  264     buf = (char *) xmlMalloc(strlen(ns->prefix) + 10);
  265     sprintf(buf, "%s:HREF", ns->prefix);
  266     res = (char *) xmlGetProp(desc, buf);
  267     xmlFree(buf);
  268     return(res);
  269 }
  270 
  271 /*
  272  * Read any resource associated to an element.
  273  */
  274 char *rdfGetElementResource(rdfSchema schema, rdfElement elem) {
  275     char *res;
  276 
  277     res = (char *) xmlGetProp(elem, "resource");
  278     return(res);
  279 }
  280 
  281 void rdfSetElementResource(rdfSchema schema, rdfElement elem, const char *URI) {
  282     xmlSetProp(elem, "resource", URI);
  283 }
  284 
  285 /**
  286  ** Routines to read/write final values.
  287  **/
  288 
  289 /*
  290  * browse the various property pertaining to this description,
  291  * and return the value which can be either a text (RDF_LEAF)
  292  * or an rdfElement (RDF_BAG, RDF_SEQ, RDF_ALT, RDF_DESC).
  293  * Having both reflect an invalid RDF document (while valid from
  294  * XML point of view).
  295  * This routine tries to ajust in case a request is done with or
  296  * or without a ns present or not on the node, and if the names
  297  * matches.
  298  *  e.g. a request for Name may return BIB:Name
  299  *    or a request for BIB:Name may return Name
  300  * if the exact match is not found.
  301  * 
  302  * Return -1 if not found
  303  *         0 if a single value is found
  304  *   RDF_xxx if a node is found.
  305  */
  306 int rdfGetValue(rdfDescription desc, const char *property, 
  307                 rdfNamespace ns, char **value, rdfElement *elem){
  308     rdfElement list = desc->xmlChildrenNode;
  309     rdfElement best = NULL;
  310     int approx = 0;
  311 
  312     if (value != NULL) *value = NULL;
  313     if (elem != NULL) *elem = NULL;
  314 
  315     while (list != NULL) {
  316         if ((list->ns == ns) && (!strcmp(list->name, property))) {
  317         /*
  318          * Found a perfect match, return it !
  319          */
  320         if (value != NULL) {
  321         *value = xmlNodeListGetString(desc->doc, list->xmlChildrenNode, 1);
  322             }
  323         if (elem != NULL) {
  324         *elem = list->xmlChildrenNode;
  325         while ((*elem != NULL) && (xmlIsBlankNode(*elem)))
  326             *elem = (*elem)->next;
  327         }
  328         if (!strcmp(list->name, "Bag")) return(RDF_BAG);
  329         if (!strcmp(list->name, "Seq")) return(RDF_SEQ);
  330         if (!strcmp(list->name, "Alt")) return(RDF_ALT);
  331         if (!strcmp(list->name, "Description")) return(RDF_DESC);
  332         return(0);
  333     }
  334     else if (((list->ns == NULL) || (ns == NULL)) &&
  335              (!strcmp(list->name, property))) {
  336         /*
  337          * If more than one "best" match exists, ignore them !
  338          */
  339         if (approx) {
  340             best = NULL;
  341         } else {
  342                 best = list;
  343         approx = 1;
  344             }
  345         }
  346     list = list->next;
  347     }
  348     if (best != NULL) {
  349     if (value != NULL) {
  350         *value = xmlNodeListGetString(desc->doc, best->xmlChildrenNode, 1);
  351     }
  352     if (elem != NULL) *elem = best->xmlChildrenNode;
  353     if (!strcmp(best->name, "Bag")) return(RDF_BAG);
  354     if (!strcmp(best->name, "Seq")) return(RDF_SEQ);
  355     if (!strcmp(best->name, "Alt")) return(RDF_ALT);
  356     if (!strcmp(best->name, "Description")) return(RDF_DESC);
  357     return(0);
  358     }
  359     return(-1);
  360 }
  361 
  362 /*
  363  * browse the various property pertaining to this description,
  364  * update the value if found on a text mode, otherwise append
  365  * a new property at the end of the list.
  366  * Note that contrary to GetValue, the check is absolute !
  367  */
  368 void rdfSetValue(rdfDescription desc, const char *property,
  369                  rdfNamespace ns, const char *value) {
  370     xmlChar *tmp;
  371     rdfElement list = desc->xmlChildrenNode;
  372 
  373     /*
  374      * Search the property.
  375      */
  376     while (list != NULL) {
  377         if ((list->ns == ns) && (!strcmp(list->name, property))) {
  378         /*
  379          * Property was found, update it !
  380          */
  381         if (list->xmlChildrenNode != NULL)
  382         xmlFreeNodeList(list->xmlChildrenNode);
  383         tmp = xmlEncodeEntitiesReentrant(desc->doc, value);
  384         list->xmlChildrenNode = xmlStringGetNodeList(desc->doc, tmp);
  385         xmlFree(tmp);
  386 
  387         return;
  388     }
  389     list = list->next;
  390     }
  391 
  392     /*
  393      * Create a new property.
  394      */
  395     tmp = xmlEncodeEntitiesReentrant(desc->doc, value);
  396     xmlNewChild(desc, ns, property, tmp);
  397     xmlFree(tmp);
  398 }
  399 
  400 /*
  401  * browse the various property pertaining to this description,
  402  * and if found remove and destroy the subtree.
  403  */
  404 void rdfRemoveProperty(rdfDescription desc, const char *property,
  405                        rdfNamespace ns) {
  406     rdfElement list = desc->xmlChildrenNode;
  407     rdfElement prev = NULL;
  408 
  409     /*
  410      * Search the property.
  411      */
  412     while (list != NULL) {
  413         if ((list->ns == ns) && (!strcmp(list->name, property))) {
  414         /*
  415          * Property was found, delete it !
  416          */
  417         if (prev == NULL)
  418             desc->xmlChildrenNode = list->next;
  419         else
  420             prev->next = list->next;
  421         list->next = NULL;
  422         
  423         xmlFreeNode(list);
  424         return;
  425     }
  426     prev = list;
  427     list = list->next;
  428     }
  429 }
  430 
  431 /**
  432  ** Routines to read/write bags
  433  **/
  434 
  435 /*
  436  * Create a new Bag.
  437  */
  438 rdfBag rdfBagCreate(rdfSchema schema, rdfDescription desc,
  439                     const char *property, rdfNamespace ns) {
  440     rdfElement cur;
  441     rdfNamespace rdf;
  442 
  443     rdf = rdfGetRdfNamespace(schema);
  444     cur = xmlNewChild(desc, ns, property, NULL);
  445     cur = xmlNewChild(cur, rdf, "Bag", NULL);
  446     return(cur);
  447 }
  448 
  449 /*
  450  * Add an element to a bag.
  451  */
  452 rdfElement rdfBagAddValue(rdfBag bag, const char *property,
  453                     rdfNamespace ns, const char *value, rdfElement elem) {
  454     rdfElement cur;
  455 
  456     if (value != NULL)
  457         cur = xmlNewChild(bag, ns, property, (char *) value);
  458     else {
  459         cur = xmlNewDocNode(bag->doc, ns, property, NULL);
  460     if (elem != NULL)
  461         xmlAddChild(cur, elem);
  462     xmlAddChild(bag, cur);
  463     }
  464     return(cur);
  465 }
  466 
  467 /**
  468  ** Routines to walk bags and sequences.
  469  **/
  470 rdfElement rdfFirstChild(rdfElement bag) {
  471     rdfElement elem = bag->xmlChildrenNode;
  472 
  473     while ((elem != NULL) && (xmlIsBlankNode(elem)))
  474         elem = elem->next;
  475     return(elem);
  476 }
  477 rdfElement rdfNextElem(rdfElement desc) {
  478     rdfElement elem = desc->next;
  479 
  480     while ((elem != NULL) && (xmlIsBlankNode(elem)))
  481         elem = elem->next;
  482     return(elem);
  483 }
  484 
  485 /**
  486  ** Direct access to Element values.
  487  **/
  488 int rdfElemGetType(rdfElement elem) {
  489     if (!strcmp(elem->name, "Bag")) return(RDF_BAG);
  490     if (!strcmp(elem->name, "Seq")) return(RDF_SEQ);
  491     if (!strcmp(elem->name, "Alt")) return(RDF_ALT);
  492     if (!strcmp(elem->name, "Description")) return(RDF_DESC);
  493     return(0);
  494 }
  495 
  496 char *rdfElemGetValue(rdfElement elem) {
  497     return(xmlNodeListGetString(elem->doc, elem->xmlChildrenNode, 1));
  498 }
  499 char *rdfElemGetPropertyName(rdfElement elem) {
  500     return(strdup(elem->name));
  501 }
  502 rdfNamespace rdfElemGetNamespace(rdfElement elem) {
  503     return(elem->ns);
  504 }
  505 void rdfElemSetValue(rdfElement elem, const char *value) {
  506     xmlChar *tmp;
  507 
  508     if (elem->xmlChildrenNode != NULL) {
  509         fprintf(stderr, "rdfElemSetValue : elem %s has xmlChildrenNode\n", elem->name);
  510     return;
  511     }
  512     if (elem->xmlChildrenNode != NULL) xmlFreeNodeList(elem->xmlChildrenNode);
  513     tmp = xmlEncodeEntitiesReentrant(elem->doc, value);
  514     elem->xmlChildrenNode = xmlStringGetNodeList(elem->doc,  tmp);
  515     xmlFree(tmp);
  516 }
  517 
  518 /************************************************************************
  519  *                                  *
  520  *              Debug                   *
  521  *                                  *
  522  ************************************************************************/
  523 
  524 #ifdef DEBUG_RDF
  525 int main(void) {
  526     rdfSchema rdf;
  527     rdfNamespace rpm;
  528     rdfDescription desc;
  529     rdfBag bag;
  530 
  531     char *value;
  532 
  533     /*
  534      * build a fake RDF document
  535      */
  536     rdf = rdfNewSchema();
  537     rpm = rdfNewNamespace(rdf, "http://www.rpm.org/", "RPM");
  538     desc = rdfAddDescription(rdf, NULL,
  539            "ftp://ftp.redhat.com/pub/contrib/i386/rpm2html-0.90-1.i386.rpm");
  540     rdfSetValue(desc, "Description", rpm, "<shade/stick & close/destroy>");
  541     rdfSetValue(desc, "Name", rpm, "rpm2html");
  542     rdfSetValue(desc, "Version", rpm, "0.90");
  543     rdfSetValue(desc, "Release", rpm, "1");
  544     bag = rdfBagCreate(rdf, desc, "Provides", rpm);
  545     rdfBagAddValue(bag, "Resource", rpm, "rpm2html", NULL);
  546     bag = rdfBagCreate(rdf, desc, "Requires", rpm);
  547     rdfBagAddValue(bag, "Resource", rpm, "libz.so.1", NULL);
  548     rdfBagAddValue(bag, "Resource", rpm, "libdb.so.2", NULL);
  549     rdfBagAddValue(bag, "Resource", rpm, "libc.so.6", NULL);
  550     rdfBagAddValue(bag, "Resource", rpm, "ld-linux.so.2", NULL);
  551 
  552     /*
  553      * Save it.
  554      */
  555     rdfWrite(rdf, "test.rdf");
  556     rdfDestroySchema(rdf);
  557 
  558     /*
  559      * Read it.
  560      */
  561     rdf = rdfRead("test.rdf");
  562 
  563     /*
  564      * print it.
  565      */
  566     rpm = rdfGetNamespace(rdf, "http://www.rpm.org/");
  567     if (rpm == NULL) fprintf(stderr, "RPM namespace not found !\n");
  568     desc = rdfFirstDescription(rdf);
  569     rdfGetValue(desc, "Name", rpm, &value, NULL);
  570     printf("Name : %s\n", value);
  571     xmlFree(value);
  572     rdfGetValue(desc, "Name", NULL, &value, NULL);
  573     printf("Name : %s\n", value);
  574     xmlFree(value);
  575     printf("\n---\n");
  576     xmlDocDump(stdout, rdf);
  577 
  578     /*
  579      * free it.
  580      */
  581     rdfDestroySchema(rdf);
  582     return(0);
  583 }
  584 #endif