Teadmiste kursuse naiteprogramm 1: erinevus redaktsioonide vahel

Allikas: Lambda
Mine navigeerimisribale Mine otsikasti
Resümee puudub
 
Resümee puudub
 
(ei näidata sama kasutaja 2 vahepealset redaktsiooni)
1. rida: 1. rida:
<pre>                           
<pre>                           
/**  
/**  
  * section:     XPath
  * section: XPath
  * synopsis:   Load a document, locate subelements with XPath, modify
  * synopsis: Load a document, locate subelements with XPath, modify
  *              said elements and save the resulting document.
  *              said elements and save the resulting document.
  * purpose:     Shows how to make a full round-trip from a load/edit/save
  * purpose: Shows how to make a full round-trip from a load/edit/save
  * usage:       xpath2 <xml-file> <xpath-expr> <new-value>
  * usage: xpath2 <xml-file> <xpath-expr> <new-value>
  * test:       xpath2 test3.xml '//discarded' discarded > xpath2.tmp ; diff xpath2.tmp  
  * test: xpath2 test3.xml '//discarded' discarded > xpath2.tmp ; diff xpath2.tmp xpath2.res ; rm xpath2.tmp
xpath2.res ; rm xpath2.tmp
  * author: Aleksey Sanin and Daniel Veillard
  * author:     Aleksey Sanin and Daniel Veillard
  * copy: see Copyright for the status of this software.
  * copy:       see Copyright for the status of this software.
  */
  */
#include <stdlib.h>
#include <stdlib.h>
26. rida: 25. rida:


static void usage(const char *name);
static void usage(const char *name);
static int example4(const char *filename, const xmlChar * xpathExpr,
                    const xmlChar * value);
static void update_xpath_nodes(xmlNodeSetPtr nodes, const xmlChar * value);


     /* free the document */
 
     xmlFreeDoc(doc);  
int
main(int argc, char **argv) {
    /* Parse command line and process file */
    if (argc != 4) {
fprintf(stderr, "Error: wrong number of arguments.\n");
usage(argv[0]);
return(-1);
    }
   
    /* Init libxml */   
    xmlInitParser();
    LIBXML_TEST_VERSION
 
    /* Do the main job */
    if (example4(argv[1], BAD_CAST argv[2], BAD_CAST argv[3])) {
usage(argv[0]);
return(-1);
    }
 
    /* Shutdown libxml */
    xmlCleanupParser();
   
    /*
    * this is to debug memory for regression tests
    */
    xmlMemoryDump();
     return 0;
}
 
/**
* usage:
* @name: the program name.
*
* Prints usage information.
*/
static void
usage(const char *name) {
     assert(name);
      
      
     return(0);
     fprintf(stderr, "Usage: %s <xml-file> <xpath-expr> <value>\n", name);
}
}


/**
/**
  * update_xpath_nodes:
  * example4:
  * @nodes:             the nodes set.
  * @filename: the input XML filename.
  * @value:             the new value for the node(s)
* @xpathExpr: the xpath expression for evaluation.
  * @value: the new node content.
*
* Parses input XML file, evaluates XPath expression and update the nodes
* then print the result.
  *
  *
  * Prints the @nodes content to @output.
  * Returns 0 on success and a negative value otherwise.
  */
  */
static void
static int
update_xpath_nodes(xmlNodeSetPtr nodes, const xmlChar* value) {
example4(const char* filename, const xmlChar* xpathExpr, const xmlChar* value) {
     int size;
     xmlDocPtr doc;
     int i;
    xmlXPathContextPtr xpathCtx;
    xmlXPathObjectPtr xpathObj;  
     int tmp;
      
      
    assert(filename);
    assert(xpathExpr);
     assert(value);
     assert(value);
     size = (nodes) ? nodes->nodeNr : 0;
 
     /* Load XML document */
    doc = xmlParseFile(filename);
    if (doc == NULL) {
fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
return(-1);
    }
 
    /* Create xpath evaluation context */
    xpathCtx = xmlXPathNewContext(doc);
    if(xpathCtx == NULL) {
        fprintf(stderr,"Error: unable to create new XPath context\n");
        xmlFreeDoc(doc);
        return(-1);
    }
    tmp=xmlXPathRegisterNs(xpathCtx,"rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
    if (tmp!=0) {
      fprintf(stderr,"Error: unable to register ns\n");
      xmlFreeDoc(doc);
      return(-1);
    }
 
    /* Evaluate xpath expression */
    xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);
    if(xpathObj == NULL) {
        fprintf(stderr,"Error: unable to evaluate xpath expression \"%s\"\n", xpathExpr);
        xmlXPathFreeContext(xpathCtx);
        xmlFreeDoc(doc);
        return(-1);
    }
 
    /* update selected nodes */
    update_xpath_nodes(xpathObj->nodesetval, value);
 
      
      
     /*
     /* Cleanup of XPath data */
    * NOTE: the nodes are processed in reverse order, i.e. reverse document
     xmlXPathFreeObject(xpathObj);
    *      order because xmlNodeSetContent can actually free up descendant
    xmlXPathFreeContext(xpathCtx);  
    *      of the node and such nodes may have been selected too ! Handling
 
    *      in reverse order ensure that descendant are accessed first, before
    /* dump the resulting document */
    *      they get removed. Mixing XPath and modifications on a tree must be
     xmlDocDump(stdout, doc);
    *      done carefully !
    */
     for(i = size - 1; i >= 0; i--) {
        assert(nodes->nodeTab[i]);
       
        xmlNodeSetContent(nodes->nodeTab[i], value);
        /*
        * All the elements returned by an XPath query are pointers to
        * elements from the tree *except* namespace nodes where the XPath
        * semantic is different from the implementation in libxml2 tree.
        * As a result when a returned node set is freed when
        * xmlXPathFreeObject() is called, that routine must check the
        * element type. But node from the returned set may have been removed
        * by xmlNodeSetContent() resulting in access to freed data.
        * This can be exercised by running
        *       valgrind xpath2 test3.xml '//discarded' discarded
        * There is 2 ways around it:
        *  - make a copy of the pointers to the nodes from the result set
        *     then call xmlXPathFreeObject() and then modify the nodes
        * or
        *  - remove the reference to the modified nodes from the node set
        *    as they are processed, if they are not namespace nodes.
        */
        if (nodes->nodeTab[i]->type != XML_NAMESPACE_DECL)
            nodes->nodeTab[i] = NULL;
    }
}


#else
int main(void) {
    fprintf(stderr, "XPath support not compiled in\n");
    exit(1);
}
#endif


     /* free the document */
     /* free the document */
97. rida: 144. rida:
/**
/**
  * update_xpath_nodes:
  * update_xpath_nodes:
  * @nodes:             the nodes set.
  * @nodes: the nodes set.
  * @value:             the new value for the node(s)
  * @value: the new value for the node(s)
  *
  *
  * Prints the @nodes content to @output.
  * Prints the @nodes content to @output.
119. rida: 166. rida:
     */
     */
     for(i = size - 1; i >= 0; i--) {
     for(i = size - 1; i >= 0; i--) {
        assert(nodes->nodeTab[i]);
assert(nodes->nodeTab[i]);
       
        xmlNodeSetContent(nodes->nodeTab[i], value);
xmlNodeSetContent(nodes->nodeTab[i], value);
        /*
/*
        * All the elements returned by an XPath query are pointers to
* All the elements returned by an XPath query are pointers to
        * elements from the tree *except* namespace nodes where the XPath
* elements from the tree *except* namespace nodes where the XPath
        * semantic is different from the implementation in libxml2 tree.
* semantic is different from the implementation in libxml2 tree.
        * As a result when a returned node set is freed when
* As a result when a returned node set is freed when
        * xmlXPathFreeObject() is called, that routine must check the
* xmlXPathFreeObject() is called, that routine must check the
        * element type. But node from the returned set may have been removed
* element type. But node from the returned set may have been removed
        * by xmlNodeSetContent() resulting in access to freed data.
* by xmlNodeSetContent() resulting in access to freed data.
        * This can be exercised by running
* This can be exercised by running
        *      valgrind xpath2 test3.xml '//discarded' discarded
*      valgrind xpath2 test3.xml '//discarded' discarded
        * There is 2 ways around it:
* There is 2 ways around it:
        *  - make a copy of the pointers to the nodes from the result set  
*  - make a copy of the pointers to the nodes from the result set  
        *    then call xmlXPathFreeObject() and then modify the nodes
*    then call xmlXPathFreeObject() and then modify the nodes
        * or
* or
        *  - remove the reference to the modified nodes from the node set
*  - remove the reference to the modified nodes from the node set
        *    as they are processed, if they are not namespace nodes.
*    as they are processed, if they are not namespace nodes.
        */
*/
        if (nodes->nodeTab[i]->type != XML_NAMESPACE_DECL)
if (nodes->nodeTab[i]->type != XML_NAMESPACE_DECL)
            nodes->nodeTab[i] = NULL;
    nodes->nodeTab[i] = NULL;
     }
     }
}
}
150. rida: 197. rida:
}
}
#endif
#endif
<pre>
 
~
</pre>
~
~
~</pre>

Viimane redaktsioon: 8. veebruar 2006, kell 20:09

                           
/** 
 * section: 	XPath
 * synopsis: 	Load a document, locate subelements with XPath, modify
 *              said elements and save the resulting document.
 * purpose: 	Shows how to make a full round-trip from a load/edit/save
 * usage:	xpath2 <xml-file> <xpath-expr> <new-value>
 * test:	xpath2 test3.xml '//discarded' discarded > xpath2.tmp ; diff xpath2.tmp xpath2.res ; rm xpath2.tmp
 * author: 	Aleksey Sanin and Daniel Veillard
 * copy: 	see Copyright for the status of this software.
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>

#if defined(LIBXML_XPATH_ENABLED) && defined(LIBXML_SAX1_ENABLED) && \
    defined(LIBXML_OUTPUT_ENABLED)


static void usage(const char *name);
static int example4(const char *filename, const xmlChar * xpathExpr,
                    const xmlChar * value);
static void update_xpath_nodes(xmlNodeSetPtr nodes, const xmlChar * value);


int 
main(int argc, char **argv) {
    /* Parse command line and process file */
    if (argc != 4) {
	fprintf(stderr, "Error: wrong number of arguments.\n");
	usage(argv[0]);
	return(-1);
    } 
    
    /* Init libxml */     
    xmlInitParser();
    LIBXML_TEST_VERSION

    /* Do the main job */
    if (example4(argv[1], BAD_CAST argv[2], BAD_CAST argv[3])) {
	usage(argv[0]);
	return(-1);
    }

    /* Shutdown libxml */
    xmlCleanupParser();
    
    /*
     * this is to debug memory for regression tests
     */
    xmlMemoryDump();
    return 0;
}

/**
 * usage:
 * @name:		the program name.
 *
 * Prints usage information.
 */
static void 
usage(const char *name) {
    assert(name);
    
    fprintf(stderr, "Usage: %s <xml-file> <xpath-expr> <value>\n", name);
}

/**
 * example4:
 * @filename:		the input XML filename.
 * @xpathExpr:		the xpath expression for evaluation.
 * @value:		the new node content.
 *
 * Parses input XML file, evaluates XPath expression and update the nodes
 * then print the result.
 *
 * Returns 0 on success and a negative value otherwise.
 */
static int 
example4(const char* filename, const xmlChar* xpathExpr, const xmlChar* value) {
    xmlDocPtr doc;
    xmlXPathContextPtr xpathCtx; 
    xmlXPathObjectPtr xpathObj; 
    int tmp;
    
    assert(filename);
    assert(xpathExpr);
    assert(value);

    /* Load XML document */
    doc = xmlParseFile(filename);
    if (doc == NULL) {
	fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
	return(-1);
    }

    /* Create xpath evaluation context */
    xpathCtx = xmlXPathNewContext(doc);
    if(xpathCtx == NULL) {
        fprintf(stderr,"Error: unable to create new XPath context\n");
        xmlFreeDoc(doc); 
        return(-1);
    }
     tmp=xmlXPathRegisterNs(xpathCtx,"rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
    if (tmp!=0) {
       fprintf(stderr,"Error: unable to register ns\n");
       xmlFreeDoc(doc);
       return(-1);
     }

    /* Evaluate xpath expression */
    xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);
    if(xpathObj == NULL) {
        fprintf(stderr,"Error: unable to evaluate xpath expression \"%s\"\n", xpathExpr);
        xmlXPathFreeContext(xpathCtx); 
        xmlFreeDoc(doc); 
        return(-1);
    }

    /* update selected nodes */
    update_xpath_nodes(xpathObj->nodesetval, value);

    
    /* Cleanup of XPath data */
    xmlXPathFreeObject(xpathObj);
    xmlXPathFreeContext(xpathCtx); 

    /* dump the resulting document */
    xmlDocDump(stdout, doc);


    /* free the document */
    xmlFreeDoc(doc); 
    
    return(0);
}

/**
 * update_xpath_nodes:
 * @nodes:		the nodes set.
 * @value:		the new value for the node(s)
 *
 * Prints the @nodes content to @output.
 */
static void
update_xpath_nodes(xmlNodeSetPtr nodes, const xmlChar* value) {
    int size;
    int i;
    
    assert(value);
    size = (nodes) ? nodes->nodeNr : 0;
    
    /*
     * NOTE: the nodes are processed in reverse order, i.e. reverse document
     *       order because xmlNodeSetContent can actually free up descendant
     *       of the node and such nodes may have been selected too ! Handling
     *       in reverse order ensure that descendant are accessed first, before
     *       they get removed. Mixing XPath and modifications on a tree must be
     *       done carefully !
     */
    for(i = size - 1; i >= 0; i--) {
	assert(nodes->nodeTab[i]);
	
	xmlNodeSetContent(nodes->nodeTab[i], value);
	/*
	 * All the elements returned by an XPath query are pointers to
	 * elements from the tree *except* namespace nodes where the XPath
	 * semantic is different from the implementation in libxml2 tree.
	 * As a result when a returned node set is freed when
	 * xmlXPathFreeObject() is called, that routine must check the
	 * element type. But node from the returned set may have been removed
	 * by xmlNodeSetContent() resulting in access to freed data.
	 * This can be exercised by running
	 *       valgrind xpath2 test3.xml '//discarded' discarded
	 * There is 2 ways around it:
	 *   - make a copy of the pointers to the nodes from the result set 
	 *     then call xmlXPathFreeObject() and then modify the nodes
	 * or
	 *   - remove the reference to the modified nodes from the node set
	 *     as they are processed, if they are not namespace nodes.
	 */
	if (nodes->nodeTab[i]->type != XML_NAMESPACE_DECL)
	    nodes->nodeTab[i] = NULL;
    }
}

#else
int main(void) {
    fprintf(stderr, "XPath support not compiled in\n");
    exit(1);
}
#endif