Teadmiste kursuse naiteprogramm 1

Allikas: Lambda
Redaktsioon seisuga 8. veebruar 2006, kell 20:03 kasutajalt Tammet (arutelu | kaastöö)
(erin) ←Vanem redaktsioon | Viimane redaktsiooni (erin) | Uuem redaktsioon→ (erin)
Mine navigeerimisribale Mine otsikasti
                           
/** 
 * 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);

    /* 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

    /* 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
<pre>
~
~
~
~