~ubuntu-branches/ubuntu/utopic/libxml2/utopic

« back to all changes in this revision

Viewing changes to doc/examples/xpath1.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-11-10 20:21:18 UTC
  • Revision ID: james.westby@ubuntu.com-20051110202118-j36kpn33k2as4xwa
Tags: upstream-2.6.22
ImportĀ upstreamĀ versionĀ 2.6.22

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** 
 
2
 * section:     XPath
 
3
 * synopsis:    Evaluate XPath expression and prints result node set.
 
4
 * purpose:     Shows how to evaluate XPath expression and register 
 
5
 *              known namespaces in XPath context.
 
6
 * usage:       xpath1 <xml-file> <xpath-expr> [<known-ns-list>]
 
7
 * test: ./xpath1 test3.xml '//child2' > xpath1.tmp ; diff xpath1.tmp xpath1.res ; rm xpath1.tmp
 
8
 * author:      Aleksey Sanin
 
9
 * copy:        see Copyright for the status of this software.
 
10
 */
 
11
#include <stdlib.h>
 
12
#include <stdio.h>
 
13
#include <string.h>
 
14
#include <assert.h>
 
15
 
 
16
#include <libxml/tree.h>
 
17
#include <libxml/parser.h>
 
18
#include <libxml/xpath.h>
 
19
#include <libxml/xpathInternals.h>
 
20
 
 
21
#if defined(LIBXML_XPATH_ENABLED) && defined(LIBXML_SAX1_ENABLED)
 
22
 
 
23
 
 
24
static void usage(const char *name);
 
25
int  execute_xpath_expression(const char* filename, const xmlChar* xpathExpr, const xmlChar* nsList);
 
26
int  register_namespaces(xmlXPathContextPtr xpathCtx, const xmlChar* nsList);
 
27
void print_xpath_nodes(xmlNodeSetPtr nodes, FILE* output);
 
28
 
 
29
int 
 
30
main(int argc, char **argv) {
 
31
    /* Parse command line and process file */
 
32
    if((argc < 3) || (argc > 4)) {
 
33
        fprintf(stderr, "Error: wrong number of arguments.\n");
 
34
        usage(argv[0]);
 
35
        return(-1);
 
36
    } 
 
37
    
 
38
    /* Init libxml */     
 
39
    xmlInitParser();
 
40
    LIBXML_TEST_VERSION
 
41
 
 
42
    /* Do the main job */
 
43
    if(execute_xpath_expression(argv[1], BAD_CAST argv[2], (argc > 3) ? BAD_CAST argv[3] : NULL) < 0) {
 
44
        usage(argv[0]);
 
45
        return(-1);
 
46
    }
 
47
 
 
48
    /* Shutdown libxml */
 
49
    xmlCleanupParser();
 
50
    
 
51
    /*
 
52
     * this is to debug memory for regression tests
 
53
     */
 
54
    xmlMemoryDump();
 
55
    return 0;
 
56
}
 
57
 
 
58
/**
 
59
 * usage:
 
60
 * @name:               the program name.
 
61
 *
 
62
 * Prints usage information.
 
63
 */
 
64
static void 
 
65
usage(const char *name) {
 
66
    assert(name);
 
67
    
 
68
    fprintf(stderr, "Usage: %s <xml-file> <xpath-expr> [<known-ns-list>]\n", name);
 
69
    fprintf(stderr, "where <known-ns-list> is a list of known namespaces\n");
 
70
    fprintf(stderr, "in \"<prefix1>=<href1> <prefix2>=href2> ...\" format\n");
 
71
}
 
72
 
 
73
/**
 
74
 * execute_xpath_expression:
 
75
 * @filename:           the input XML filename.
 
76
 * @xpathExpr:          the xpath expression for evaluation.
 
77
 * @nsList:             the optional list of known namespaces in 
 
78
 *                      "<prefix1>=<href1> <prefix2>=href2> ..." format.
 
79
 *
 
80
 * Parses input XML file, evaluates XPath expression and prints results.
 
81
 *
 
82
 * Returns 0 on success and a negative value otherwise.
 
83
 */
 
84
int 
 
85
execute_xpath_expression(const char* filename, const xmlChar* xpathExpr, const xmlChar* nsList) {
 
86
    xmlDocPtr doc;
 
87
    xmlXPathContextPtr xpathCtx; 
 
88
    xmlXPathObjectPtr xpathObj; 
 
89
    
 
90
    assert(filename);
 
91
    assert(xpathExpr);
 
92
 
 
93
    /* Load XML document */
 
94
    doc = xmlParseFile(filename);
 
95
    if (doc == NULL) {
 
96
        fprintf(stderr, "Error: unable to parse file \"%s\"\n", filename);
 
97
        return(-1);
 
98
    }
 
99
 
 
100
    /* Create xpath evaluation context */
 
101
    xpathCtx = xmlXPathNewContext(doc);
 
102
    if(xpathCtx == NULL) {
 
103
        fprintf(stderr,"Error: unable to create new XPath context\n");
 
104
        xmlFreeDoc(doc); 
 
105
        return(-1);
 
106
    }
 
107
    
 
108
    /* Register namespaces from list (if any) */
 
109
    if((nsList != NULL) && (register_namespaces(xpathCtx, nsList) < 0)) {
 
110
        fprintf(stderr,"Error: failed to register namespaces list \"%s\"\n", nsList);
 
111
        xmlXPathFreeContext(xpathCtx); 
 
112
        xmlFreeDoc(doc); 
 
113
        return(-1);
 
114
    }
 
115
 
 
116
    /* Evaluate xpath expression */
 
117
    xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);
 
118
    if(xpathObj == NULL) {
 
119
        fprintf(stderr,"Error: unable to evaluate xpath expression \"%s\"\n", xpathExpr);
 
120
        xmlXPathFreeContext(xpathCtx); 
 
121
        xmlFreeDoc(doc); 
 
122
        return(-1);
 
123
    }
 
124
 
 
125
    /* Print results */
 
126
    print_xpath_nodes(xpathObj->nodesetval, stdout);
 
127
 
 
128
    /* Cleanup */
 
129
    xmlXPathFreeObject(xpathObj);
 
130
    xmlXPathFreeContext(xpathCtx); 
 
131
    xmlFreeDoc(doc); 
 
132
    
 
133
    return(0);
 
134
}
 
135
 
 
136
/**
 
137
 * register_namespaces:
 
138
 * @xpathCtx:           the pointer to an XPath context.
 
139
 * @nsList:             the list of known namespaces in 
 
140
 *                      "<prefix1>=<href1> <prefix2>=href2> ..." format.
 
141
 *
 
142
 * Registers namespaces from @nsList in @xpathCtx.
 
143
 *
 
144
 * Returns 0 on success and a negative value otherwise.
 
145
 */
 
146
int 
 
147
register_namespaces(xmlXPathContextPtr xpathCtx, const xmlChar* nsList) {
 
148
    xmlChar* nsListDup;
 
149
    xmlChar* prefix;
 
150
    xmlChar* href;
 
151
    xmlChar* next;
 
152
    
 
153
    assert(xpathCtx);
 
154
    assert(nsList);
 
155
 
 
156
    nsListDup = xmlStrdup(nsList);
 
157
    if(nsListDup == NULL) {
 
158
        fprintf(stderr, "Error: unable to strdup namespaces list\n");
 
159
        return(-1);     
 
160
    }
 
161
    
 
162
    next = nsListDup; 
 
163
    while(next != NULL) {
 
164
        /* skip spaces */
 
165
        while((*next) == ' ') next++;
 
166
        if((*next) == '\0') break;
 
167
 
 
168
        /* find prefix */
 
169
        prefix = next;
 
170
        next = (xmlChar*)xmlStrchr(next, '=');
 
171
        if(next == NULL) {
 
172
            fprintf(stderr,"Error: invalid namespaces list format\n");
 
173
            xmlFree(nsListDup);
 
174
            return(-1); 
 
175
        }
 
176
        *(next++) = '\0';       
 
177
        
 
178
        /* find href */
 
179
        href = next;
 
180
        next = (xmlChar*)xmlStrchr(next, ' ');
 
181
        if(next != NULL) {
 
182
            *(next++) = '\0';   
 
183
        }
 
184
 
 
185
        /* do register namespace */
 
186
        if(xmlXPathRegisterNs(xpathCtx, prefix, href) != 0) {
 
187
            fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix, href);
 
188
            xmlFree(nsListDup);
 
189
            return(-1); 
 
190
        }
 
191
    }
 
192
    
 
193
    xmlFree(nsListDup);
 
194
    return(0);
 
195
}
 
196
 
 
197
/**
 
198
 * print_xpath_nodes:
 
199
 * @nodes:              the nodes set.
 
200
 * @output:             the output file handle.
 
201
 *
 
202
 * Prints the @nodes content to @output.
 
203
 */
 
204
void
 
205
print_xpath_nodes(xmlNodeSetPtr nodes, FILE* output) {
 
206
    xmlNodePtr cur;
 
207
    int size;
 
208
    int i;
 
209
    
 
210
    assert(output);
 
211
    size = (nodes) ? nodes->nodeNr : 0;
 
212
    
 
213
    fprintf(output, "Result (%d nodes):\n", size);
 
214
    for(i = 0; i < size; ++i) {
 
215
        assert(nodes->nodeTab[i]);
 
216
        
 
217
        if(nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) {
 
218
            xmlNsPtr ns;
 
219
            
 
220
            ns = (xmlNsPtr)nodes->nodeTab[i];
 
221
            cur = (xmlNodePtr)ns->next;
 
222
            if(cur->ns) { 
 
223
                fprintf(output, "= namespace \"%s\"=\"%s\" for node %s:%s\n", 
 
224
                    ns->prefix, ns->href, cur->ns->href, cur->name);
 
225
            } else {
 
226
                fprintf(output, "= namespace \"%s\"=\"%s\" for node %s\n", 
 
227
                    ns->prefix, ns->href, cur->name);
 
228
            }
 
229
        } else if(nodes->nodeTab[i]->type == XML_ELEMENT_NODE) {
 
230
            cur = nodes->nodeTab[i];        
 
231
            if(cur->ns) { 
 
232
                fprintf(output, "= element node \"%s:%s\"\n", 
 
233
                    cur->ns->href, cur->name);
 
234
            } else {
 
235
                fprintf(output, "= element node \"%s\"\n", 
 
236
                    cur->name);
 
237
            }
 
238
        } else {
 
239
            cur = nodes->nodeTab[i];    
 
240
            fprintf(output, "= node \"%s\": type %d\n", cur->name, cur->type);
 
241
        }
 
242
    }
 
243
}
 
244
 
 
245
#else
 
246
int main(void) {
 
247
    fprintf(stderr, "XPath support not compiled in\n");
 
248
    exit(1);
 
249
}
 
250
#endif